<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: MAYNO</title>
    <description>The latest articles on Forem by MAYNO (@mayno).</description>
    <link>https://forem.com/mayno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3885114%2Fe6016014-ab4e-4d88-a8ed-0619553ba001.jpg</url>
      <title>Forem: MAYNO</title>
      <link>https://forem.com/mayno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mayno"/>
    <language>en</language>
    <item>
      <title>How to Scrape Swedish Real Estate Data from Hemnet (No Code, No API)</title>
      <dc:creator>MAYNO</dc:creator>
      <pubDate>Thu, 30 Apr 2026 14:53:30 +0000</pubDate>
      <link>https://forem.com/mayno/how-to-scrape-swedish-real-estate-data-from-hemnet-no-code-no-api-324o</link>
      <guid>https://forem.com/mayno/how-to-scrape-swedish-real-estate-data-from-hemnet-no-code-no-api-324o</guid>
      <description>&lt;p&gt;&lt;em&gt;Extract property listings, prices, agent contacts, and more from Sweden's #1 real estate platform in minutes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you've ever tried to get structured data from Hemnet.se — Sweden's dominant real estate marketplace with over 90% market share — you've probably hit the same wall: &lt;strong&gt;there is no official Hemnet API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No developer portal. No API keys. No documentation.&lt;/p&gt;

&lt;p&gt;Yet investors, PropTech startups, market researchers, and real estate agencies all need this data. They need prices, addresses, agent contacts, property sizes, and viewing dates — at scale, in a format they can actually work with.&lt;/p&gt;

&lt;p&gt;This article shows you exactly how to get it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Hemnet?
&lt;/h2&gt;

&lt;p&gt;Hemnet is Sweden's largest real estate platform. If a property is for sale in Sweden, it's almost certainly listed on Hemnet. That near-total market dominance makes it the single most valuable source of Swedish housing market data.&lt;/p&gt;

&lt;p&gt;A typical listing includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Property details&lt;/strong&gt;: type (Villa, Lägenhet, Radhus), rooms, living area (m²), land area, year built, floor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location&lt;/strong&gt;: address, neighborhood, city (kommun), county (län), distance to coast&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial data&lt;/strong&gt;: asking price (SEK), price per m², monthly fee (Avgift), annual running costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent information&lt;/strong&gt;: agent name, agency, phone number, email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media&lt;/strong&gt;: property images, full description, upcoming viewing dates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is that none of this is accessible through an API. Hemnet is a consumer-facing website — not a data platform. To extract this data programmatically, you need a scraper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Just Write Your Own Scraper?
&lt;/h2&gt;

&lt;p&gt;You could. But there are real challenges:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bot detection.&lt;/strong&gt; Hemnet uses anti-bot protection. A naive scraper will get blocked within minutes. Handling this properly requires proxy rotation, realistic browser headers, and rate limiting — all of which add significant complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance.&lt;/strong&gt; When Hemnet updates their site (which they do), your scraper breaks. You're now on the hook for keeping it working.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure.&lt;/strong&gt; Running scrapers at scale requires servers, scheduling, monitoring, and storage. That's a project in itself.&lt;/p&gt;

&lt;p&gt;For most use cases — market research, investment analysis, lead generation, building a product — the better approach is to use a pre-built, maintained scraper that handles all of this for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Hemnet Scraper on Apify
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com" rel="noopener noreferrer"&gt;Apify&lt;/a&gt; is a web scraping and automation platform that hosts thousands of pre-built scrapers called "Actors." The &lt;strong&gt;Hemnet Scraper&lt;/strong&gt; actor extracts property listings from Hemnet.se with no code, no infrastructure, and no maintenance on your end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actor link:&lt;/strong&gt; &lt;a href="https://apify.com/mayno/hemnet-scraper" rel="noopener noreferrer"&gt;apify.com/mayno/hemnet-scraper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what you get per listing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"21538498"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.hemnet.se/bostad/lagenhet-3rum-..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scraped_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-04-28T18:30:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Karlslundsvägen 15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"neighborhood"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Barkarbystaden"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Järfälla kommun"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"county"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stockholms län"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"distance_to_coast_m"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"property_details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lägenhet i Barkarbystaden"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lägenhet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tenure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bostadsrätt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rooms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"living_area_sqm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;74&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"year_built"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amenities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Balkong"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fiber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hiss"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"financials"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"asking_price_sek"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3250000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price_per_sqm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;43919&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"monthly_fee_sek"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna Lindström"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fastighetsbyrån"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+46-8-123-4567"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.lindstrom@fastighetsbyran.se"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nyproducerad lägenhet i populära Barkarbystaden..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"viewing_dates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"2026-05-03 11:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-05-05 14:00"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"images"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://bilder.hemnet.se/..."&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;30+ fields per property. Clean, structured JSON. Ready to import into Excel, Airtable, a database, or your own application.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Use It (Step by Step)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create a free Apify account
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://apify.com" rel="noopener noreferrer"&gt;apify.com&lt;/a&gt; and sign up. The free plan includes $5 in monthly credits — enough to scrape roughly 2,500 properties at no cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Open the Hemnet Scraper
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;a href="https://apify.com/mayno/hemnet-scraper" rel="noopener noreferrer"&gt;apify.com/mayno/hemnet-scraper&lt;/a&gt; and click &lt;strong&gt;"Try for free"&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Choose your scraping mode
&lt;/h3&gt;

&lt;p&gt;The actor supports two modes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mode 1: Search URL (recommended for bulk scraping)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the most powerful option. Go to Hemnet.se, apply your filters (location, property type, price range, etc.), and copy the URL from your browser. Paste it into the scraper.&lt;/p&gt;

&lt;p&gt;For example, to scrape all villas in Stockholm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.hemnet.se/bostader?item_types[]=villa&amp;amp;location_ids[]=17744
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set &lt;strong&gt;Maximum Pages&lt;/strong&gt; to control how many result pages to scrape. Each page contains approximately 50 properties. Setting it to 5 gives you ~250 properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mode 2: Direct Property URLs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have specific listings you want to track, paste their URLs directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.hemnet.se/bostad/lagenhet-3rum-barkarbystaden-jarfalla-kommun-karlslundsvagen-15-21538498
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is ideal for monitoring specific properties over time or tracking price changes on a watchlist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Run the scraper
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;"Start"&lt;/strong&gt;. The scraper typically processes 50–100 properties per minute. A run of 250 properties takes about 3–4 minutes and costs roughly $0.50.&lt;/p&gt;

&lt;p&gt;You'll see results appearing in real time in the Output tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Export your data
&lt;/h3&gt;

&lt;p&gt;Once complete, export your data in any format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JSON&lt;/strong&gt; — for developers and APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSV&lt;/strong&gt; — for Excel, Google Sheets, or data analysis tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excel (.xlsx)&lt;/strong&gt; — pre-formatted spreadsheet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML Table&lt;/strong&gt; — for quick web viewing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Real estate market analysis
&lt;/h3&gt;

&lt;p&gt;Scrape a city or region periodically to track price trends over time. Compare asking prices across neighborhoods, property types, or years of construction. Identify where prices are rising or falling before the mainstream data catches up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weekly scheduled scrape of Stockholm apartments&lt;/li&gt;
&lt;li&gt;Import into Google Sheets via Apify's Google Sheets integration&lt;/li&gt;
&lt;li&gt;Build a chart tracking median price per m² over time&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Investment opportunity identification
&lt;/h3&gt;

&lt;p&gt;Set up a daily scrape of specific search criteria — undervalued properties, specific neighborhoods, below-market prices for a given size. Get alerts when new listings appear matching your investment criteria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Daily scrape of Gothenburg villas under 4M SEK with 5+ rooms&lt;/li&gt;
&lt;li&gt;Send results to Airtable&lt;/li&gt;
&lt;li&gt;Use Airtable automations to alert you on new matches&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Agent lead generation
&lt;/h3&gt;

&lt;p&gt;The scraper extracts agent name, agency, phone, and email for every listing. If you offer services to Swedish real estate agents — photography, moving companies, renovation, mortgage brokering — this data is a direct pipeline to your audience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important note on GDPR:&lt;/strong&gt; Agent contact information is publicly listed by agents themselves on Hemnet. However, if you use this data for outreach, ensure your use case complies with GDPR and Swedish data protection law. Use it responsibly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Automated property valuation
&lt;/h3&gt;

&lt;p&gt;Build a valuation model using scraped data. With price, size, location, year built, and amenities all structured, you have everything you need to train a price prediction model or build a comparative market analysis tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Academic and journalistic research
&lt;/h3&gt;

&lt;p&gt;Sweden's housing affordability is a significant political topic. Researchers at Swedish universities (KTH, Stockholm University, Chalmers) can use this data to study price trends, geographic disparities, and housing supply across municipalities — without manually collecting data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scheduling and Automation
&lt;/h2&gt;

&lt;p&gt;One of Apify's most powerful features is scheduling. You can set the Hemnet Scraper to run automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily&lt;/strong&gt; — for monitoring active listings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekly&lt;/strong&gt; — for market trend tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monthly&lt;/strong&gt; — for long-term analysis datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined with Apify's integrations, you can build fully automated pipelines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trigger&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New listings scraped&lt;/td&gt;
&lt;td&gt;→ Push to Google Sheets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price drops detected&lt;/td&gt;
&lt;td&gt;→ Send Slack notification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weekly scrape complete&lt;/td&gt;
&lt;td&gt;→ Email CSV to your team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New agent contacts found&lt;/td&gt;
&lt;td&gt;→ Add to Airtable CRM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Set it up once, and your Swedish real estate dataset updates itself automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connecting via API
&lt;/h2&gt;

&lt;p&gt;If you're building an application or want to trigger scrapes programmatically, Apify provides a REST API. You can start runs, check status, and retrieve results with a simple HTTP call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Trigger a scrape via Apify API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.apify.com/v2/acts/mayno~hemnet-scraper/runs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;YOUR_API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;searchUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.hemnet.se/bostader?location_ids[]=17744&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;maxPages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it straightforward to integrate Hemnet data into your own product — a dashboard, a mobile app, a CRM, or an automated reporting tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Data Can You Extract?
&lt;/h2&gt;

&lt;p&gt;Here's the complete field reference:&lt;/p&gt;

&lt;h3&gt;
  
  
  Root fields
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique Hemnet property ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Full listing URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scraped_at&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ISO 8601&lt;/td&gt;
&lt;td&gt;Timestamp of scrape&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Location
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;address&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Street address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;neighborhood&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Area/district name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;city&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Municipality (kommun)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;county&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;County (län)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;distance_to_coast_m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Distance to nearest coast in meters&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Property Details
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Villa, Lägenhet, Radhus, Kedjehus, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tenure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Äganderätt, Bostadsrätt, or Hyresrätt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rooms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of rooms (e.g., 3.5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;living_area_sqm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Heated living space (Boarea)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;supplemental_area_sqm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Secondary space (Biarea)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;land_area_sqm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Plot area (for Villa/Radhus)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;year_built&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Construction year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;floor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Floor position (e.g., "2/4")&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amenities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array: Balkong, Garage, Fiber, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;is_new_construction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Financials
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;asking_price_sek&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Listed price in SEK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;price_per_sqm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SEK per m² of living area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;monthly_fee_sek&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Monthly Avgift (Bostadsrätt only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;running_costs_year_sek&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Annual Driftskostnad (Villa/Radhus)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agent full name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;agency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agency name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;phone&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Swedish phone number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agent email&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Content
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full listing text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;viewing_dates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Upcoming visning dates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;images&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array of high-resolution image URLs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need a Hemnet account?&lt;/strong&gt;&lt;br&gt;
No. The scraper accesses only publicly visible listing data, which requires no login.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I get a search URL?&lt;/strong&gt;&lt;br&gt;
Go to Hemnet.se, apply your filters (location, price, property type), and copy the URL from your browser's address bar. Paste it directly into the scraper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I scrape multiple cities in one run?&lt;/strong&gt;&lt;br&gt;
Yes — Hemnet supports multiple location IDs in a single search URL. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.hemnet.se/bostader?location_ids[]=17744&amp;amp;location_ids[]=17755
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens if Hemnet changes their site?&lt;/strong&gt;&lt;br&gt;
The actor is actively maintained. If Hemnet updates their page structure and the scraper breaks, it will be fixed and a new version deployed — typically within 48 hours of detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I run this on a schedule?&lt;/strong&gt;&lt;br&gt;
Yes. Apify has built-in scheduling. Set it to run daily, weekly, or at any custom interval from the actor's Settings tab.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Manual scraping&lt;/th&gt;
&lt;th&gt;Hemnet Scraper on Apify&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;Days to weeks&lt;/td&gt;
&lt;td&gt;2 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Your responsibility&lt;/td&gt;
&lt;td&gt;Handled for you&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bot detection&lt;/td&gt;
&lt;td&gt;You figure it out&lt;/td&gt;
&lt;td&gt;Built-in proxy rotation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Server + dev time&lt;/td&gt;
&lt;td&gt;From $2.00 per 1,000 results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduling&lt;/td&gt;
&lt;td&gt;Build it yourself&lt;/td&gt;
&lt;td&gt;One-click&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Export formats&lt;/td&gt;
&lt;td&gt;Whatever you code&lt;/td&gt;
&lt;td&gt;JSON, CSV, Excel, HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you need Swedish real estate data and don't want to spend weeks building and maintaining a scraper, the Hemnet Scraper on Apify is the most direct path to clean, structured data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ Try it free:&lt;/strong&gt; &lt;a href="https://apify.com/mayno/hemnet-scraper" rel="noopener noreferrer"&gt;apify.com/mayno/hemnet-scraper&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;I build data extraction tools and automation actors on Apify. My scrapers help investors, researchers, and developers access structured data from platforms that don't offer official APIs.&lt;/p&gt;

&lt;p&gt;Follow me on X: &lt;a href="https://x.com/Amine_Fer" rel="noopener noreferrer"&gt;@Amine_Fer&lt;/a&gt;&lt;br&gt;
Apify profile: &lt;a href="https://apify.com/mayno" rel="noopener noreferrer"&gt;apify.com/mayno&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written as part of the &lt;br&gt;
Bright Data Dev.to challenge on web scraping.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>brightdatachallenge</category>
      <category>webdev</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Half Your Free Trial Signups Are Fake: Here's How to Fix It</title>
      <dc:creator>MAYNO</dc:creator>
      <pubDate>Fri, 17 Apr 2026 20:06:35 +0000</pubDate>
      <link>https://forem.com/mayno/half-your-free-trial-signups-are-fake-heres-how-to-fix-it-3h75</link>
      <guid>https://forem.com/mayno/half-your-free-trial-signups-are-fake-heres-how-to-fix-it-3h75</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Every SaaS Faces
&lt;/h2&gt;

&lt;p&gt;Fake signups from disposable emails are killing your metrics. Someone signs up with &lt;code&gt;throwaway@mailinator.com&lt;/code&gt;, uses your free trial, and vanishes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wastes customer success time&lt;/li&gt;
&lt;li&gt;Inflates your user count (fake growth)&lt;/li&gt;
&lt;li&gt;Costs you money (server resources, email sends)&lt;/li&gt;
&lt;li&gt;Makes your analytics useless&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: Email Risk Scoring
&lt;/h2&gt;

&lt;p&gt;Instead of just validating syntax, check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is it from a disposable provider? (mailinator, guerrillamail, etc.)&lt;/li&gt;
&lt;li&gt;Does the domain have MX records?&lt;/li&gt;
&lt;li&gt;Free provider vs business email?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What Good Email Validation Detects
&lt;/h2&gt;

&lt;p&gt;A proper email risk scorer checks multiple signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disposable domains&lt;/strong&gt;: Is it from Mailinator, Guerrilla Mail, or 500+ other temporary providers?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MX records&lt;/strong&gt;: Can the domain actually receive emails?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider type&lt;/strong&gt;: Free (Gmail/Yahoo) vs Business (company.com)?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role-based emails&lt;/strong&gt;: Generic addresses like info@, admin@, noreply@&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk level&lt;/strong&gt;: Low, Medium, or High&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Implement It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: DIY Solution (Free, But Manual)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use the GitHub disposable-email-domains list
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;DISPOSABLE_DOMAINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_disposable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;DISPOSABLE_DOMAINS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 2: Use a Ready-Made API (Faster Setup)
&lt;/h3&gt;

&lt;p&gt;Or skip all that complexity and use a ready-made solution.&lt;/p&gt;

&lt;p&gt;I built this to solve the problem: &lt;a href="https://apify.com/mayno/email-risk-scorer" rel="noopener noreferrer"&gt;https://apify.com/mayno/email-risk-scorer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get out of the box:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;500+ disposable domains&lt;/strong&gt; detected (Mailinator, Guerrilla Mail, YOPmail, etc.)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;MX record validation&lt;/strong&gt; - checks if the domain can actually receive emails&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Email provider identification&lt;/strong&gt; - detects Google Workspace, Microsoft 365, Zoho, etc.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Free vs business email classification&lt;/strong&gt; - Gmail/Yahoo vs company domains&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Role-based email detection&lt;/strong&gt; - flags generic addresses (info@, admin@, noreply@)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Automatic syntax validation&lt;/strong&gt; - RFC-compliant email format checking&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Risk level scoring&lt;/strong&gt; - returns low/medium/high based on multiple signals&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Batch processing&lt;/strong&gt; - validate up to 10,000 emails per run&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No maintenance&lt;/strong&gt; - disposable domain list updated automatically&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Fast processing&lt;/strong&gt; - handles 1,000 emails in ~3-5 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup time: 5 minutes.&lt;/strong&gt; Here's the complete implementation for an Express.js signup route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApifyClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apify-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apifyClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_APIFY_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Check email risk (one API call)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apifyClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mayno/email-risk-scorer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apifyClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;listItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailRisk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Block disposable emails&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailRisk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDisposable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Disposable email addresses are not allowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Block high-risk emails&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailRisk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;riskLevel&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This email address cannot be used for registration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Optional: Flag free email providers for review&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailRisk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFreeProvider&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;emailRisk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasMXRecord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Log for manual review&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Suspicious signup:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Proceed with signup&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example API response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isValid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isDisposable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isFreeProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isBusinessEmail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isRoleBasedEmail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hasMXRecord"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mxProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mail.mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"riskLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Disposable/temporary email provider"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this beats the DIY approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No code to maintain (I handle updates)&lt;/li&gt;
&lt;li&gt;No DNS infrastructure to manage&lt;/li&gt;
&lt;li&gt;No edge cases to debug&lt;/li&gt;
&lt;li&gt;No weekly domain list updates&lt;/li&gt;
&lt;li&gt;Works day one, scales to millions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time saved:&lt;/strong&gt; ~6 hours initial setup + 1-2 hours/month maintenance = &lt;strong&gt;ship faster, focus on your product&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Pick what works for your stage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Early/MVP&lt;/strong&gt;: DIY approach&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling&lt;/strong&gt;: Use an API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Want to test it out? The actor is live on Apify with a free tier: &lt;a href="https://apify.com/mayno/email-risk-scorer" rel="noopener noreferrer"&gt;https://apify.com/mayno/email-risk-scorer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions? Feedback? Drop a comment below.&lt;/strong&gt; I'm actively working on this and would love to hear what features would be most useful!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
