# Eniro Scraper — Swedish Business Directory Leads (Företag) (`worktech/eniro-scraper`) Actor

Scrape Swedish business leads from eniro.se: company name, phone, email, address, postal code, city and website. Search by keyword and city (rörmokare Stockholm) and export B2B leads to JSON, CSV or Excel. Pay per result — $2 per 1,000 records.

- **URL**: https://apify.com/worktech/eniro-scraper.md
- **Developed by:** [Per Schondell](https://apify.com/worktech) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 business records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Eniro Scraper — Swedish Business Directory Leads (Företag)

The **eniro scraper** that turns eniro.se — Sweden's largest business directory — into a clean B2B lead list: company name, **phone number, email, street address, postal code, city, and website** for any business category in any Swedish town. A true **Swedish business directory scraper** and a practical **hitta.se alternative** for lead generation: type `rörmokare` + `Stockholm`, press Start, export **Sweden B2B leads** to JSON, CSV, or Excel.

**Business listings only** — the actor collects company records, not private persons.

### What can you do with it?

- **Get Swedish business leads with phone numbers** — every record carries the phone shown on eniro.se, normalized for dialers and CRMs
- **Export eniro.se search results to CSV or Excel** — one clean row per company, stable columns, ready for import
- **Build B2B prospect lists by trade and city** — `elektriker` in Göteborg, `redovisningsbyrå` in Malmö, `snickare` nationwide
- **Enrich leads with email and website** — the actor opens each company's detail page, where eniro keeps email and website, and merges them in
- **Feed AI agents and pipelines** — structured JSON output via API, webhooks, or the Apify MCP server, so agents can call this scraper as a tool

### Pricing

**$2 per 1,000 business records** ($0.002 per record). You pay only for records actually delivered to your dataset — a blocked or empty search costs nothing.

| Scenario | Records | Run cost |
|----------|---------|----------|
| Plumbers in Stockholm | ~500 | ~$1 |
| One trade across the 20 largest Swedish cities | ~3,000 | ~$6 |
| Nationwide category sweep | ~10,000 | ~$20 |

#### Listing mode vs enriched mode (proxy cost on your account)

Residential proxy traffic is billed by Apify on your account, separately from the actor price. The two modes differ a lot there (measured):

| Mode | Fields | Proxy data | Approx. proxy cost |
|------|--------|-----------|--------------------|
| **Listing** (default) | name, phone, address, postal code, city, eniro URL | ~0.036 MB/record | well under $1 per 1,000 records |
| **Enriched** (`fetchContactDetails: true`) | + email & website from each company's detail page | ~0.9 MB/record | roughly $8 per 1,000 records |

Enriched mode is fully supported but **opt-in**: switch on **Fetch email & website** only when you need emails, and consider capping `maxResultsPerSearch` for the first enriched run.

### How to scrape eniro.se (step by step)

1. Click **Try for free** — you need a free Apify account.
2. Enter one or more **Search terms** in Swedish (e.g. `rörmokare`, `elektriker`).
3. Enter **Locations** (e.g. `Stockholm`, `Kiruna`) — or leave empty to search all of Sweden.
4. Optionally adjust **Max results per search**, and switch on **Fetch email & website** if you want enriched contact records (see the proxy-cost table above — roughly $8 per 1,000 records of proxy traffic on your account).
5. Click **Start**, then open the **Dataset** tab and export as JSON, CSV, Excel, HTML, or XML.

Prefer pasting URLs? Put eniro.se listing pages straight into **Start URLs** instead of search terms.

#### Input example

```json
{
  "searchTerms": ["rörmokare", "elektriker"],
  "locations": ["Stockholm", "Uppsala"],
  "maxResultsPerSearch": 200,
  "requestDelayMs": 5000,
  "fetchContactDetails": true,
  "includeSoleTraders": false
}
```

#### Output example (one dataset record)

```json
{
  "name": "Kiruna Rör AB",
  "phone": "098012345",
  "email": "info@kirunaror.se",
  "address": "Gruvvägen 12",
  "postalCode": "981 32",
  "city": "Kiruna",
  "categories": ["rörmokare"],
  "website": "https://kirunaror.se",
  "eniroUrl": "https://www.eniro.se/kiruna-r%C3%B6r-ab/12345/firma",
  "sourceUrl": "https://www.eniro.se/r%C3%B6rmokare+kiruna/f%C3%B6retag",
  "searchTerm": "rörmokare",
  "location": "Kiruna",
  "scrapedAt": "2026-08-15T10:30:00+00:00"
}
```

Missing values are explicit `null`, so CSV and Excel exports always have the same columns.

### Use it from code or AI agents

```bash
curl -X POST "https://api.apify.com/v2/acts/worktech~eniro-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms":["rörmokare"],"locations":["Stockholm"],"maxResultsPerSearch":100}'
```

The actor also works with n8n, Make, Zapier, webhooks, and the **Apify MCP server** — its structured output is designed to be consumed by AI agents directly.

### Why this scraper?

- **The URL scheme that actually works** — eniro.se silently ignores `?where=` and `?page=` query parameters and serves the same national top-25 regardless. This actor uses the path-based scheme (`/rörmokare+stockholm/företag/2`) verified against the live site, so city filtering and pagination really apply.
- **Real contact data, not just names** — email and website live only on each company's detail page; the actor fetches them there and merges them into the record.
- **Cloudflare-aware by design** — anti-detect Firefox (Camoufox) with locale/geo alignment, cookie-consent handling, paced fresh-tab detail fetches, and local exponential backoff on blocks.
- **No silent failures** — a blocked search surfaces as a named error in the run summary instead of quietly returning nothing, and a sustained contact-page wall aborts the run rather than delivering half-empty records. You are never billed for records you didn't receive: data is pushed before it is charged.

Also from worktech: [Lean Shopify Scraper](https://apify.com/worktech/lean-shopify-scraper) — pay-per-result Shopify product and price scraping.

### FAQ

**Is this a hitta.se alternative for lead generation?**
Yes in outcome: both directories cover Swedish businesses. This actor scrapes eniro.se, which exposes rich per-company detail pages (email, website, opening hours) that make it well suited for B2B lead lists.

**Do I get email addresses?**
When eniro.se has one, yes — but only in enriched mode. Email lives on the company detail page, so switch on **Fetch email & website** (adds roughly $8 per 1,000 records of residential-proxy cost on your account). Coverage varies by trade — not every Swedish business publishes an email.

**Can I export the leads to CSV or Excel?**
Yes. Every run produces a dataset downloadable as CSV, Excel, JSON, HTML, or XML from the Apify Console, or via API.

**Does it collect private persons?**
No. The actor is business-only by policy. Sole-trader businesses listed under a personal name (common for tradespeople) are excluded by default and only included if you switch on **includeSoleTraders**.

**What should I put in Search terms — Swedish or English?**
Swedish, matching eniro.se's own categories: `rörmokare` (plumber), `elektriker` (electrician), `tandläkare` (dentist), `redovisningsbyrå` (accounting firm).

**Why is the run slower than a plain HTTP scraper?**
eniro.se sits behind Cloudflare bot protection. The actor uses a real anti-detect browser with human-like pacing — that's what makes the data come out correct and complete. The default listing-only mode is the fast one; enriched mode adds one detail-page load per company.

**Is it legal to scrape eniro.se?**
The actor collects publicly visible business information (the same data any visitor sees) and no private-person data. Whether scraping fits your use case depends on your jurisdiction and the site's terms — when in doubt, consult a lawyer.

### Limitations

- **Email/website coverage depends on eniro.se** — companies without a published email simply have `email: null`.
- **Requires Swedish residential proxies for reliable runs** — the default proxy configuration is Apify residential, country SE. Datacenter proxies will get challenged far more often.
- **Detail-page enrichment (opt-in) adds one page load per company** — expect roughly 3–7 seconds and ~0.9 MB of proxy traffic per fully enriched record; the default listing-only mode is the right choice for bulk name/phone runs.
- **Pagination is capped at 50 pages (~1,250 records) per search combination** as a runaway guard — split very large categories by city to get everything.

### Roadmap

Eniro Group runs the same directory platform in Norway (gulesider.no) and Denmark (krak.dk, degulesider.dk). The scraper's parsing is already parameterized by site, so sibling actors for those markets are planned next.

### Status

**v0.1** — port of a production scraper that has crawled eniro.se at scale; 88 unit tests passing against recorded fixtures, including a live-captured Cloudflare challenge page.

# Actor input Schema

## `searchTerms` (type: `array`):

Business categories or keywords to search on eniro.se, in Swedish (e.g. rörmokare, elektriker, redovisningsbyrå). Each term is combined with every location.

## `locations` (type: `array`):

Swedish cities or towns to search in (e.g. Stockholm, Göteborg, Kiruna). Leave empty to search nationally.

## `startUrls` (type: `array`):

Paste eniro.se listing URLs directly, e.g. https://www.eniro.se/rörmokare+stockholm/företag — used instead of or in addition to search terms.

## `maxResultsPerSearch` (type: `integer`):

Cap on business records per search term x location combination. 0 = no cap (scrapes every result page).

## `requestDelayMs` (type: `integer`):

Politeness delay between paginated listing requests. Lower is faster but raises the chance of Cloudflare rate blocks.

## `fetchContactDetails` (type: `boolean`):

Email and (usually) website exist only on each company's detail page. COST NOTE: this fetches one detail page per company via residential proxy — adds roughly $8 per 1,000 records of proxy cost on your account, on top of the actor price. Off by default: the default listing-only run delivers name, phone, address, postal code and city at a fraction of the proxy cost.

## `includeSoleTraders` (type: `boolean`):

eniro lists some sole-trader businesses under the owner's personal name (e.g. 'Anders Svensson' in a plumber search). Off by default: only records with a company-style name are kept.

## `proxyConfiguration` (type: `object`):

eniro.se sits behind Cloudflare — Swedish residential proxies are strongly recommended.

## Actor input object example

```json
{
  "searchTerms": [
    "rörmokare"
  ],
  "locations": [
    "Stockholm"
  ],
  "maxResultsPerSearch": 100,
  "requestDelayMs": 5000,
  "fetchContactDetails": false,
  "includeSoleTraders": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "SE"
  }
}
```

# Actor output Schema

## `businessRecords` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "rörmokare"
    ],
    "locations": [
        "Stockholm"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "SE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("worktech/eniro-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["rörmokare"],
    "locations": ["Stockholm"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "SE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("worktech/eniro-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "rörmokare"
  ],
  "locations": [
    "Stockholm"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "SE"
  }
}' |
apify call worktech/eniro-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,worktech/eniro-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/hr9ghR7aAc3J24rBd/builds/pkkEE7IqKGlJaaZ22/openapi.json
