# Reco.se Scraper - Swedish Trades Leads with Phone & Website (`scrapersdelight/reco-se-scraper`) Actor

Scrape Reco.se, Sweden's company-review site, for trades leads: plumbers, electricians, builders, painters, roofers and 47 more trades. Phone, website, address, rating and review count per company, nationwide or by place. $0.0045 per company with a phone or website; the rest are never charged.

- **URL**: https://apify.com/scrapersdelight/reco-se-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.50 / 1,000 per company with a phone or websites

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🔧 Reco.se Scraper — Swedish Trades Leads with Phone & Website

**Turn [Reco.se](https://www.reco.se) — Sweden's largest independent company-review site — into a
lead list of Swedish tradespeople.** Pick trades (`rörmokare`, `elektriker`, `byggföretag`, `målare`,
`takläggare`… 52 building and installation trades by default, or any of Reco's ~440 categories) and,
optionally, places (`Uppsala`, `Stockholm`, `Södermalm`, `Skåne`). You get one row per company with
the fields a sales or dialer team works from: **phone number (as printed + E.164), own website, street
address, postcode, town, coordinates** — plus star rating, review count, the 1–5★ distribution,
Reco's own trust rating, whether the company has claimed or verified its page, opening hours and
every category and area it is listed in.

**Measured, not estimated** (live runs on builds 0.1.3–0.1.6, 2026-09-23):

- every plumber Reco lists nationwide: **693 companies found, 693 opened**, **88.7% with a phone**,
  **47.8% with their own website**, **90.3% reachable** (phone or website). All 77 area pages that print
  a total were matched exactly by what the Actor collected.
- all 52 default trades, all of Sweden, with `completeSweep` (run aa8Xx47dHKsLXmW4M, 36 min): **5,660 trade
  companies found**, **85.6% with a phone**, **53.1% with a website**, **4,988 delivered and billed** (88.1%);
  **1,246 of 1,256** area pages that print a total were fully reached.
- delivered rows == charged events on every run (e.g. 626 delivered / 626 charged).

**$4.50 per 1,000 companies with a phone or website.** Companies with neither are never charged. No
login, no proxy, no start fee.

***

### 💡 What does this Actor do?

Reco.se shows at most **25 companies per category page** ("Topp 25"), with no page 2. Most scrapers
stop there. This Actor walks **down Reco's own area tree** — Sweden → län → kommun → stadsdel — from
every page that is full, until every branch fits on one page, and checks what it collected against
the total each city page prints (*"93 rekommenderade rörmokare i Stockholm"*):

| Where | Reco shows | This Actor collects |
|---|---|---|
| Plumbers, Stockholm | 25 on the page, "93" printed | **93 of 93** (48 district pages walked, 26 sibling pages rejected) |
| Builders, Stockholm | 25 on the page, "300" printed | **300 of 300** |
| Plumbers, all of Sweden | 25 on the national page | **693** from 153 area pages |
| Builders, Göteborg | 25 on the page, "57" printed, **no district pages exist** | 25 by walking; **47 of 57** with `completeSweep` |

Where Reco has no sub-area pages (Göteborg, Malmö, some Stockholm suburbs), the rest of the list is
not linked from any category page. Turn on **`completeSweep`** and the Actor also reads Reco's
company sitemap (~43,400 company pages) and keeps every company whose **own** categories and areas
match your input. The run summary tells you per area how many companies Reco says it lists and how
many you got.

**Three ways to run it:**

| You give it | You get |
|---|---|
| categories (+ optional places) | every company Reco lists in them — walk only (fast), or walk + sitemap (`completeSweep`, complete) |
| categories + `updatedSince` | only companies whose Reco page changed since that date — a weekly "new & changed" feed |
| `profileUrls` | exactly those companies |

### 📤 What you get — one row per company

| Field | What it is |
|---|---|
| **`phone`** | The company's phone number **exactly as Reco prints it** (`0108-88 52 40`) — from the company's JSON-LD and its own "Ring" button, never from review text |
| **`phoneE164`** | The same number as `+46…`, by reformatting only (null when that would need a guess) |
| `phoneIsMobile` | `true` for Swedish mobile ranges 070/072/073/076/079 |
| **`website`** / `websiteDomain` | The company's own website (Reco's website button / `sameAs`), and its host |
| **`street`**, **`postalCode`**, **`city`**, `countryCode` | Postal address |
| `latitude`, `longitude` | Map position |
| `companyName`, `profileUrl`, `profileSlug`, `venueId` | Identity; `venueId` is Reco's own company id (the de-duplication key) |
| `primaryCategory`, `primaryCategoryLabel` | Main Reco category (`rörmokare` / `Rörmokare`) |
| `categories` | Every Reco category the company is listed in |
| `listedAreas` | Areas it is listed in (`stockholms-län`, `stockholm`, `flysta`) |
| `schemaTypes` | Business types Reco assigns (`Plumber`, `Electrician`, `HVACBusiness`, `RoofingContractor`…) |
| `rating`, `reviewCount`, `ratingDistribution` | Average stars, number of reviews, count per star |
| `trustLevel` | Reco's credibility rating of the reviews: `Låg` / `Ok` / `Bra` / `Mycket Bra` |
| `claimedProfile`, `verifiedCompany` | The company has claimed its page / given Reco full insight into its customer system |
| `reviewInvitePolicy`, `recoInsight` | Who the company asks for reviews, and how much insight Reco has |
| `onRecoSince` | Year the company joined Reco (claimed pages) |
| `description`, `openingHours`, `awardsCount`, `logoUrl` | "Om företaget" text, opening hours, badges, logo |
| `recentReviews` | Up to 5 latest reviews (date, stars, headline, text, reviewer's display name, link) when `includeReviews` > 0 |
| `foundInCategory`, `foundInArea`, `foundVia` | Where this run found it (`listing`, `sitemap` or `url`) |
| `phoneSourcesAgree` | `true` when the JSON-LD number and the call button carry the same digits |
| `hasReachableContact`, `scrapedAt` | Phone or website present (what you pay for); collection time |

Not included, and why: **email** — Reco does not publish company email addresses (its contact form
routes through Reco); **organisation number** — not printed on any of the 77 company pages inspected
by hand (50 recon pages + the 27 test fixtures).

### 📊 Field fill — measured on real runs

Two frames, because one sample describes a sample, not the directory. Contact fields first.
"Found" includes companies without contact (they are skipped, not charged).

| Field | All plumbers in Sweden (693 found) | Electricians, painters, builders, roofers in Göteborg + Malmö, top-25 pages (136 found) | All 52 trades, all of Sweden, complete sweep (5,660 found) |
|---|---|---|---|
| **reachable (phone or website)** | **90.3%** | **89.0%** | **88.1%** |
| **`phone`** | **88.7%** | **86.8%** | **85.6%** |
| **`website`** | **47.8%** | **74.3%** | **53.1%** |
| `phoneE164` (of rows with a phone) | 99.8% | 100% | 99.98% |
| `street` / `postalCode` / `city` | 98% | 100% | 97.5% |
| `claimedProfile` | 45% | 74% | 50% |
| `verifiedCompany` | 15% | 23% | 15% |
| `description` | 42% | 70% | 47% |
| `openingHours` | 11% | 18% | 10% |

What the table says, plainly: **a phone number is on ~87–89% of trade companies; a website on about
half nationally** and on three in four of the top-ranked city companies (top-ranked companies are
mostly claimed pages, which carry more). Unclaimed pages (Reco-built, one or two reviews) are where
phone and website are missing.

One printed number in 693 plumber pages could not be put into E.164 without guessing (`0070-27 50
147`) — it ships as printed with `phoneE164: null`. Two plumbers print their number as `46…` without
the `+` (`4610-22 27 991`); a Swedish national number always starts with `0`, so the leading `46` is
the country code and the E.164 form is `+46102227991` — reformatting, not repair.

### ⚙️ Input

| Field | Default | What it does |
|---|---|---|
| `categories` | 52 trades | Reco category names as the site spells them in its URLs (`rörmokare`, `elektriker`, `byggföretag`…). A category URL also works |
| `allCategories` | `false` | Every category in Reco's category sitemap (~440) |
| `locations` | all of Sweden | Places as Reco names them: `uppsala`, `Stockholm`, `Södermalm`, `Stockholms län`, `Skåne`. Sub-areas are included; sibling municipalities a city page also links to are not |
| `profileUrls` | — | Your own list of company pages (overrides categories) |
| `maxResults` | `50` | Stop after this many delivered companies (0 = no limit) |
| `onlyWithContact` | `true` | Skip (never charge) companies with neither phone nor website. Off = deliver them free |
| `requirePhone` / `requireWebsite` | `false` | Keep only companies with a phone / with a website |
| `includeReviews` | `0` | Add up to 5 latest reviews per company |
| `completeSweep` | `false` | After the area walk, read the company sitemap to reach companies no category page links (see above). Plan on ~45–60 min for a nationwide trades run and raise the run timeout |
| `updatedSince` | — | `YYYY-MM-DD`: only companies whose page changed since then (sitemap-based feed) |
| `maxConcurrency` | `8` | Parallel requests (max 16) |
| `proxyConfiguration` | no proxy | Reco answers Apify's network directly. If you set a proxy, use RESIDENTIAL |

#### Example inputs

```json
{ "categories": ["rörmokare"], "locations": ["uppsala"], "maxResults": 50 }
```

Plumbers in Uppsala (the demo: 16 listed, 14 with contact, ~3 s).

```json
{ "categories": ["elektriker", "byggföretag"], "locations": ["göteborg"], "maxResults": 0, "completeSweep": true, "requirePhone": true }
```

Every electrician and builder in Göteborg with a phone number.

```json
{ "maxResults": 0, "updatedSince": "2026-09-16" }
```

All 52 trades, only companies whose Reco page changed in the last week.

### 🧾 Example row (real, from run aa8Xx47dHKsLXmW4M)

```json
{
  "venueId": 382218,
  "profileSlug": "rormannen-i-bromma-ab",
  "profileUrl": "https://www.reco.se/rormannen-i-bromma-ab",
  "companyName": "Rörmannen i Bromma AB",
  "phone": "08-36 28 61",
  "phoneE164": "+468362861",
  "phoneIsMobile": false,
  "website": "http://www.rormannen.se",
  "websiteDomain": "rormannen.se",
  "street": "Spångavägen 320",
  "postalCode": "16346",
  "city": "Spånga",
  "countryCode": "SE",
  "latitude": 59.36977940000001,
  "longitude": 17.9016304,
  "primaryCategory": "rörmokare",
  "primaryCategoryLabel": "Rörmokare",
  "categories": ["rörmokare", "luftvärmepump", "bergvärme", "byggvaruhus"],
  "listedAreas": ["stockholms-län", "stockholm", "flysta"],
  "schemaTypes": ["Plumber", "HVACBusiness", "HardwareStore"],
  "foundInCategory": "rörmokare",
  "foundInArea": null,
  "foundVia": "listing",
  "rating": 4.5,
  "reviewCount": 1941,
  "ratingDistribution": { "1": 32, "2": 45, "3": 87, "4": 490, "5": 1287 },
  "claimedProfile": true,
  "verifiedCompany": true,
  "trustLevel": "Mycket Bra",
  "reviewInvitePolicy": "99% av alla sina kunder",
  "recoInsight": "Reco har full insyn",
  "onRecoSince": 2013,
  "description": "Välkommen till Rörmannen i Bromma AB - din lokala rörmokare! Vi är ett ett installationsföretag som hjälper både företag, privatpersoner och bostadsrättsföreningar i Norrort, Västerort, Söderort …",
  "openingHours": [{ "days": "Mån-Sön", "hours": "07:00-21:00" }],
  "awardsCount": 13,
  "logoUrl": "https://d1soclrdty2wh7.cloudfront.net/eyJidWNrZXQiOiJzdGF0aWMucmVjby5zZSIsImtleSI6ImxvZ29zLzE0NDA3MzkwODE2OTdfeU16SzlwQ09fb3JpZ2luYWwucG5nIiwiZWRpdHMiOnsicmVzaXplIjp7IndpZHRoIjoyODgsImhlaWdodCI6MTkyLCJmaXQiOiJjb250YWluIiwiYmFja2dyb3VuZCI6eyJyIjoyNTUsImciOjI1NSwiYiI6MjU1LCJhbHBoYSI6MX19fX0=",
  "recentReviews": [],
  "phoneSourcesAgree": true,
  "hasReachableContact": true,
  "scrapedAt": "2026-09-23T05:07:08.051Z"
}
```

(`description` shortened here.)

With `includeReviews: 1`, `recentReviews` looks like this (real, run icM8KIUIW1WQPFP8q):

```json
[{ "date": "2026-09-18", "rating": 5, "headline": "Bra bemötande", "text": "Bra bemötande, proffsigt hanterat! Rekommenderas", "author": "Lars B", "reviewUrl": "https://www.reco.se/r/3345505" }]
```

### 💰 Pricing

**Pay per event: $0.0045 per company with a phone or website ($4.50 per 1,000).** No start fee, no
monthly fee.

You are charged **only** for a company that is delivered to your dataset **and** publishes a phone
number or its own website — once per company per run (de-duplicated on Reco's company id, even when
the company appears in several categories and areas). You are **never** charged for companies with
neither (skipped, or delivered free with `onlyWithContact: false`), pages that no longer exist, pages
we could not reach, duplicates, companies outside your categories/places found by the sitemap sweep,
or rows your filters removed. Rows are charged as they are delivered, so a run that hits your spending
cap stops with every delivered row paid for.

| Run | Companies | Cost |
|---|---|---|
| Default input (`maxResults` 50) | 50 | $0.23 |
| Plumbers in Uppsala | 14 | $0.06 |
| Every plumber in Sweden | 626 | $2.82 |
| All 52 trades, all of Sweden (complete sweep) | 4,988 | $22.45 |

### 🔁 Run summary

Every run writes `RUN_SUMMARY` to its key-value store: delivered and billed counts; the kinds of
"nothing" kept apart (**page gone** · **no phone and no website** · **unreachable after retries** ·
**outside your categories/places**); for every category × place, the total Reco prints, how many
companies were found and how many area pages were walked; the floor check (every area page that
prints a total, and any page where fewer companies were reached than listed); and HTTP statistics.

### ❓ FAQ

**Why not just read the category page?** It holds 25 companies. Every plumber in Sweden is 693
companies across 153 area pages.

**Why is `completeSweep` off by default?** The area walk reaches every company wherever Reco has
sub-area pages, in seconds to minutes. The sweep reads ~43,000 company pages to find the ones Reco
never links from a category page — worth it for a complete city list in Göteborg or Malmö, overkill
for Uppsala. You are charged the same per delivered company either way.

**Can I get emails?** Reco does not publish them. Use the `website` column with a website contact
extractor.

**Is the phone ever from a review?** No. Phone numbers come only from the company's structured data
and its own call button; a number written inside a review text can never become the company's
phone (tested).

**Why do some companies have no area?** Companies listed in several categories show their
categories without areas; the Actor falls back to the breadcrumb (e.g. `stockholms-län > huddinge`).
Where neither exists, `listedAreas` is empty.

### ⚠️ Honest limits

- **Reco shows 25 companies per page.** The area walk reaches the rest where sub-area pages exist;
  where they do not, only `completeSweep` does. Even then, **10 of 1,256** area totals stayed short
  (331 of 356 companies across those 10 pages, e.g. builders in Göteborg 47/57, Huddinge 46/50): those
  companies are listed under the area but neither linked from any category page nor carrying that
  area/category on their own page. The run summary names every short page.
- **One electrician in Stockholm (126 of 127) was not reachable by any area page** — nor by any of
  the 246 electrician area pages in Reco's own sitemap (124).
- **No email, no organisation number** — Reco does not publish them.
- **Website fill is ~48% across all plumbers**, higher among top-ranked companies; unclaimed pages
  rarely carry one.

# Actor input Schema

## `categories` (type: `array`):

Reco.se categories to collect, spelled as the site spells them in its URLs (reco.se/kategori/<name>/1), e.g. "rörmokare", "elektriker", "byggföretag", "målare", "takläggare". A full category URL also works. The default is 52 building and installation trades (plumbers, electricians, builders, painters, roofers, tilers, sheet-metal, floors, heat pumps, solar, ventilation, drainage, locksmiths and more). Any category on the site can be used — see reco.se/kategori.

## `allCategories` (type: `boolean`):

On: collect every category Reco.se lists in its category sitemap (~440, including restaurants, hairdressers, car repair, real-estate agents...). Leave off for trades only.

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

Limit to places: a municipality, city, district or county as Reco.se names it, e.g. "uppsala", "Stockholm", "Södermalm", "Stockholms län", "Skåne". Empty = all of Sweden. Every category is collected in every place, including all of the place's sub-areas (Stockholm includes Södermalm, Kungsholmen, Bromma...).

## `profileUrls` (type: `array`):

Your own list of Reco.se company pages (https://www.reco.se/<company> or just the <company> part). When given, only these companies are collected.

## `maxResults` (type: `integer`):

Stop after this many companies are delivered. 0 = no limit (every company in the chosen categories and places).

## `onlyWithContact` (type: `boolean`):

On (default): companies that publish neither a phone number nor a website are skipped and never charged. Off: they are delivered too, free of charge.

## `requirePhone` (type: `boolean`):

Skip companies without a phone number (skipped companies are never charged).

## `requireWebsite` (type: `boolean`):

Skip companies without their own website (skipped companies are never charged).

## `includeReviews` (type: `integer`):

Add up to the 5 most recent reviews (date, stars, headline, text, reviewer's display name) to each company row. 0 = none.

## `completeSweep` (type: `boolean`):

Reco.se shows at most 25 companies per category page. The Actor walks down into sub-areas (län > kommun > stadsdel) to get past that, which reaches every company where sub-area pages exist (measured: 93 of 93 plumbers in Stockholm, 693 plumbers nationwide). Some big cities have NO sub-area pages (Göteborg: 25 of 57 builders reachable). On: after the walk, also read Reco's company sitemap (~43,000 pages) and keep every company whose own categories and areas match your input. Slower (roughly 45-60 min for the full sitemap — raise the run timeout), and you are still only charged for delivered companies.

## `updatedSince` (type: `string`):

A date (YYYY-MM-DD). Reads only company pages Reco's sitemap marks as modified on or after this date and keeps those in your categories/places - a cheap weekly 'new and changed' feed. Uses the sitemap only (category pages carry no dates).

## `maxConcurrency` (type: `integer`):

How many pages to fetch at once.

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

Reco.se answers Apify's own network directly, so no proxy is needed (default). If you want one, pick the RESIDENTIAL group; if a configured proxy cannot be created the run continues directly.

## `debugSaveRawSamples` (type: `boolean`):

Save up to 12 raw HTML pages to the key-value store for troubleshooting.

## Actor input object example

```json
{
  "categories": [
    "rörmokare"
  ],
  "allCategories": false,
  "locations": [
    "uppsala"
  ],
  "profileUrls": [],
  "maxResults": 50,
  "onlyWithContact": true,
  "requirePhone": false,
  "requireWebsite": false,
  "includeReviews": 0,
  "completeSweep": false,
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "debugSaveRawSamples": false
}
```

# Actor output Schema

## `leads` (type: `string`):

The dataset of Reco.se companies (one item per company, de-duplicated on Reco's venue id).

## `runSummary` (type: `string`):

Delivered, billed and skipped counts, each area's own listed total vs companies collected, and HTTP statistics.

# 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 = {
    "categories": [
        "rörmokare"
    ],
    "locations": [
        "uppsala"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/reco-se-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 = {
    "categories": ["rörmokare"],
    "locations": ["uppsala"],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/reco-se-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 '{
  "categories": [
    "rörmokare"
  ],
  "locations": [
    "uppsala"
  ],
  "maxResults": 50
}' |
apify call scrapersdelight/reco-se-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/reco-se-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/HhIDBSpbAQfBMQrDU/builds/ZR9Yuzw2udGeEZPYO/openapi.json
