# Kompass B2B Company Scraper — Archived Global Directory (`scrapersdelight/kompass-b2b-scraper`) Actor

Kompass company records rebuilt from PUBLIC WEB ARCHIVES, not a live pull — the live site is behind an anti-bot wall. 828,183 archived company pages measured, 62 countries. Name, address, phone, website, employee band, coordinates, and every row's capture date. Most captures are 2014-2018.

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

## Pricing

$2.00 / 1,000 per company returneds

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?

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

## 🗄️ Kompass B2B Company Scraper — Archived Global Directory

> **Read this before anything else: these rows come out of PUBLIC WEB ARCHIVES, not out of a live
> request to Kompass.** This Actor never contacts kompass.com. It reads captures of Kompass company
> pages that the **Internet Archive Wayback Machine** and **Common Crawl** already hold, and every
> row ships with the exact date its page was captured (`captureDate`). Each row is that page's
> **earliest** archived capture on or after the year you ask for, so the shipped default run comes
> back **~79% captured 2014-2018** (measured: 119 of 150 rows on a 150-row run) and only ~2% captured 2025.
> Across the archive as a whole, **2.5-2.9% of Kompass company pages carry a capture from 2024 or
> later.** **If you need today's data, this is not the tool** — stop here and buy a live scraper
> instead.

**What you get instead:** the whole corpus, in bulk, cheaply, with no anti-bot fight —
**828,183 Kompass company pages counted as reachable** across 62 countries, at **$0.002 per
company ($2 per 1,000)**, carrying `name`, `country`, `city`, `postalCode`, `street`, `phone`,
`website`, `domain`, `employees` (+ numeric `employeesMin` / `employeesMax`), `foundedYear`,
`vatNumber`, `registrationNumber`, `latitude`, `longitude`, `activities`, `description`,
`executives`, `kompassId` — and `captureDate`, `sourceArchive` and `archiveUrl` so you can audit
the age of every single row.

```json
{
  "countries": ["DE"],
  "source": "wayback",
  "minCaptureYear": "any",
  "maxCompanies": 60,
  "strictCountry": true
}
```

Click **Try for free** and press **Start** — that block is literally the input the Actor ships
with, and it costs **$0.12**. It is a deliberately small first click that finishes in about a
minute; raise `maxCompanies` (up to 100,000) and the run timeout with it for a real pull.

***

### 🤔 Why buy archived data at all?

Because the live directory is not available to buy at any price, and it hasn't been for a while.

`kompass.com` is behind an **interactive DataDome challenge**. That is not a "add a proxy and
retry" wall — it is a wall this Actor deliberately does not try to climb. The measurement is on
the record: across 32 Common Crawl indexes, **3,560 distinct Kompass company URLs are in the
index, but only 161 of them carry a status-200 body.** The other ~3,400 are HTTP 403/405 — *Common
Crawl's own crawler is blocked at the same edge everyone else is.* You can see the block in the
archived response headers themselves (`x-archive-orig-x-datadome: protected`).

So the honest trade is this:

| | Live scraping of this site | This Actor |
|---|---|---|
| Data age | today | measured per row, mostly 2014-2018 |
| Anti-bot | interactive challenge, per request | none — reads a public dataset |
| Reliability | breaks when the wall changes | archives don't change |
| Cost per row | $0.003-$0.011 on the Store today | **$0.002, no run-start fee** |
| Volume you can actually get | whatever gets past the wall | **828,183 companies measured** |

And B2B firmographics age **unevenly**, which is the part that makes this worth buying:

- A company's **registered name, street address, city, VAT number, founding year and
  geo-coordinates** barely move. A 2015 capture of those is still a 2015-accurate address, and for
  most established industrial firms that is still today's address.
- A **landline phone number** at a manufacturer is one of the stickiest fields in B2B data.
- **Website, employee band and executives** are the fields that go stale. Treat them as leads to
  verify, not as facts.

The single best use of this dataset is as a **TAM / enrichment base**: 828k company records with
name + address + coordinates + activity that you match against your CRM, or feed into an
email-finder, not as a ready-to-dial call list.

***

### 📊 The measurements (what was counted, and what is an estimate)

#### How big is the archived corpus?

**828,183 distinct Kompass company IDs** were counted as **status-200 archived detail pages** in
the Wayback Machine on **2026-08-16**. That is an enumerated union of the archive index, not an
extrapolation. Per country host:

| Host enumerated | Archived company pages |
|---|---|
| us.kompass.com | **257,490** |
| it.kompass.com | 76,046 |
| de.kompass.com | 69,947 |
| in.kompass.com | 69,632 |
| pl.kompass.com | 69,071 |
| es.kompass.com | 68,998 |
| cn.kompass.com | 59,488 |
| gb.kompass.com | 50,785 |
| be.kompass.com | 48,441 |
| nl.kompass.com | 32,832 |
| fr.kompass.com | 28,476 *(partial — see below)* |
| tw.kompass.com | 17,396 *(re-counted independently 2026-08-17)* |
| Sum of the rows above | 848,602 |
| **Distinct companies (deduplicated union)** | **828,183** |

**Why the total is smaller than the sum:** Kompass country hosts cross-list each other's
companies, so the same `kompassId` shows up on more than one host and is counted **once**. Measured
on the two hosts re-counted for this audit: 15,989 of tw.kompass.com's 17,396 pages (92%) carry a
`TW` ID, and 2,090 of the first 2,143 de.kompass.com pages (98%) carry a `DE` ID — the rest are
other countries' companies re-listed there. The 2.4% gap between 848,602 and 828,183 is that
overlap. Country filtering in this Actor works on the **ID prefix**, not the host, so you get the
country you asked for either way.

**828,183 is a floor, and here is exactly why.** Only **12 of Kompass's 62 country hosts** were
enumerated, and the French host stopped at 18 of its 102 index pages when archive.org began
returning empty pages (the run backed off rather than hammer it). France is the largest host in the
whole index, so its true contribution is likely closer to 250,000 than 28,476.

A free **Coverage check** run on Apify on 2026-08-17 measured the index depth of all 62 hosts:
**925 CDX index pages** across the **58 hosts that answered** (4 were rate-limited that minute, so
925 is itself a floor). Companies per index page, measured by dividing each fully enumerated host's
exact count by its page count, is **1,725-4,087 with an average of 2,530** (es 1,725 · pl 1,818 ·
in 1,989 · tw 2,175 · nl 2,189 · it 2,376 · gb 2,418 · be 2,422 · de 2,798 · cn 3,131 · us 4,087).
At that density 925 pages implies roughly **2.3 million** archived company pages, and **1.6-3.8
million** at the extreme densities. Treat that as an estimate; **828,183 is the part that was
actually counted.** Tick **Coverage check** in the input and the Actor re-measures
the page counts for you, live and **for $0**.

#### How old is it? (this is the number that decides whether you should buy)

Measured, not guessed. The Wayback index was re-queried with `from=` floors to read recency
directly (re-verified 2026-08-17):

| | |
|---|---|
| nl.kompass.com pages with a 2024-or-later capture | **970 of 32,832 = 3.0%** |
| tw.kompass.com pages with a 2024-or-later capture | **441 of 17,396 = 2.5%** |
| Extrapolating that rate to the whole corpus | roughly **20,000-25,000** companies captured 2024+ |
| Pages with *any* 2022-or-later capture | **nl 1,272 = 3.9% · tw 2,943 = 16.9%** (it varies a lot by host) |
| Pages with *any* 2019-or-later capture | **nl 1,939 = 5.9% · tw 8,957 = 51%** |
| First-capture timestamps landing in 2015 alone | **84,107** |
| Common Crawl status-200 detail captures by year | 2023 = 101 · 2024 = 32 · 2025 = 25 · 2026 = 5 (newest **2026-06-18**) |

**Read the capture-date mechanic before you read those numbers.** The archive index is queried
with `collapse=urlkey`, which returns **one row per page: its earliest capture**, or its earliest
capture on/after `minCaptureYear` when you set one. So a default run hands you each company's
*oldest* snapshot even where a newer one exists — that is why a 150-row German run measured
**119 rows (79%) captured 2014-2018, 29 rows 2020-2022, 3 rows 2025**. Raising `minCaptureYear`
does not just filter: it pulls a **later capture of the same companies**, at the price of dropping
every company the archive has not re-visited since that year.

**In plain words: this is a large, old dataset with a small fresh edge.** Set `minCaptureYear` to
`2024` and you get the fresh ~2-3%; leave it on `any` and you get depth at its oldest. Either way
`captureDate` is a first-class column, so you can filter after the fact too.

#### Does the data actually come out clean?

**208 archived bodies were downloaded for real** (163 from Common Crawl by WARC byte-range, 45 from
the Wayback Machine) and run through **the exact parser this Actor ships**:

| Set | Bodies | Produced a billable company record |
|---|---|---|
| Common Crawl (2023-2026 captures) | 163 | **161 = 99%** |
| Wayback, 2022+ captures | 25 | **25 = 100%** |
| Wayback, 2014-2018 captures | 20 | **20 = 100%** |
| **Total** | **208** | **206 = 99%** |

Zero CAPTCHAs. Zero truncated bodies. Every one of the 208 came back as a full 250-460 KB company
page. The two rejects were pages that carried a name and country but no address, phone, website,
activity or employee band — and **a record that fails to parse is never pushed and never charged.**

#### Field fill on a real run

Counted field-by-field on the **58 delivered (and charged) rows** of a default German run on Apify,
**2026-08-19** (run `hADdRXDeQFZNQPIJc`, 188 s, 38 legacy + 19 modern + 1 unknown page template),
and consistent with the 150-row runs of 2026-08-17. Percentages move several points between runs
because the archive hands back a slightly different legacy/modern mix each time:

| Field | Fill |
|---|---|
| `name`, `country`, `kompassId`, `captureDate`, `sourceArchive`, `archiveUrl` | **100%** |
| `city`, `postalCode`, `street`, `address` | 98% |
| `executives` | 98% |
| `phone` | 97% |
| `latitude` / `longitude` | 95% |
| `website` / `domain` | 93% |
| `employees` (+ numeric min/max) | 93% / 91% |
| `foundedYear` | 83% |
| `activityCode` | 100% |
| `activities[]` | 92% |
| `industry` (activity label) | 87% |
| `naceCode` | 81% |
| `vatNumber` | 79% |
| `description` | 68% |
| `registrationNumber` | 21% |
| `email` | **0% — never promised, see below** |
| `revenue` | **not a field — see below** |

**How the classification and VAT fields were measured (2026-08-19).** All **62 distinct archived
company bodies** returned by the German sample runs were re-downloaded from `web.archive.org` and
grepped field by field, so these numbers are counted against raw bytes rather than against what the
parser happened to return. That audit found four fields the parser was *not* reading on the
2014-2018 **legacy** template, and they are now read: the legacy pages publish the official codes in
a separate `Andere Klassifikationen` block (NACE Rev.2 / ISIC 4 / national WZ) and the Kompass
activity code as the anchor id of the activity tree, and the 2019+ **modern** pages nest a hidden
"call this company" modal inside the VAT table cell. Measured on the same 62 bodies, before -> after:
`naceCode` **15% -> 81%**, `activityCode` **29% -> 100%**, `industry` **53% -> 87%**,
`activities` **53% -> 92%**, `vatNumber` **58% -> 79%**.

**What is genuinely not on the page**, checked the same way and stated honestly:
`email` **0/62** — no company mailto: exists in any of the 62 bodies (the only ones present belong
to Kompass itself); Kompass sells the address rather than publishing it. `registrationNumber`
**13/62** — of the 49 rows that ship an empty value, **zero** have a register-shaped value anywhere
in the body, and the legacy template has no register row at all. `industry` is a *classification
label*: where a page carries only marketing prose and no classification, the field ships empty
rather than shipping a sentence — the prose is still there verbatim in `description`.

Field fill varies by era, by country and by archive. Split by page template across those 62 bodies
(42 legacy / 19 modern): `website` **93% legacy / 100% modern**, `executives` **100% / 100%**,
`vatNumber` **76% / 89%**, `foundedYear` **93% / 63%**, `naceCode` **88% / 68%**,
`activityCode` **100% / 100%**, `industry` **88% / 79%**. The **Common Crawl** sample behaves differently again — its 2023-2026
captures carried a website on only **12%** of pages, because the modern live template moved the
website link behind an EasyBusiness upsell that the *Wayback* captures in this run predate. Rule
of thumb: Wayback rows are rich on `website`, Common Crawl rows are fresh but thin on it.

***

### 🚀 Quick start

1. Click **Try for free** → the input opens **already filled in**.
2. Press **Start**. 60 German companies, $0.12, about a minute. Measured on 2026-08-17: **every
   run returned the full 60 rows, 100% of downloaded pages parsed into billable records, 60/60
   distinct `kompassId`, and exactly one charged event per delivered row.** (The same input at 150
   companies returns 150 rows in 85-300 seconds, depending on how fast the archive is answering —
   which is why the shipped default is 60 and why big pulls need a bigger run timeout.)
3. Open the **Dataset** tab → **Export** to CSV, Excel, JSON, XML, or pull it from the API.
4. Now make it yours: change **Countries**, add a keyword to **Company name contains**, or raise
   **Earliest capture year** to 2024 if freshness matters more than volume to you.

#### Free coverage check

```json
{ "listCountries": true }
```

Returns one row for each of the **62** Kompass country hosts with the number of index pages the
Wayback Machine holds for it, an estimated company count, and the exact enumerated count for the
12 hosts that were counted in full. Verified on Apify 2026-08-17: **62 rows, 0 charged events, $0
in Actor charges** — the rows are pushed without the billing event.

Two caveats, because they are real: the run takes **several minutes** (archive.org rate-limits its
index endpoint and this walks 62 hosts), and archive.org sometimes answers **HTTP 429 to every
request from a datacentre IP**. When that happens the run stops re-counting after 5 refusals and
reports the 2026-08-16 enumeration instead; the **`indexStatus`** column on every row tells you
whether that row was counted live (`measured-live`) or is the cached enumeration
(`archive-rate-limited` / `not-queried-archive-rate-limited`).

#### Other useful inputs

```json
{ "countries": ["IT", "ES"], "nameContains": ["srl", "logistica"], "maxCompanies": 500 }
```

```json
{ "countries": ["US"], "minCaptureYear": "2024", "maxCompanies": 300 }
```

```json
{ "source": "commoncrawl", "countries": ["DE", "FR", "IT"], "maxCompanies": 100 }
```

```json
{ "companyUrls": ["DE664484", "https://de.kompass.com/c/imo-oberflachentechnik-gmbh/de635069/"] }
```

***

### 📋 Every field

| Field | What it is |
|---|---|
| `kompassId` | Kompass's own company ID, e.g. `DE664484`. **The dedupe key**, and its 2-letter prefix is the company's real country. |
| `name` | Registered / trading name as Kompass published it |
| `country` / `countryName` | ISO-2 code from the Kompass ID, plus the English name |
| `city`, `postalCode`, `street`, `address` | Postal address, split and joined |
| `latitude`, `longitude` | Geo-coordinates Kompass published for the site. Present in **both** page eras. |
| `phone` | Company switchboard, international format |
| `website`, `domain` | Company website and its bare domain (era-dependent — see above) |
| `email` | Almost always empty; Kompass gates it behind a paid unlock. **Never promised.** |
| `employees` | Employee band, in the page's own language ("Von 100 bis 249 Mitarbeiter") |
| `employeesMin`, `employeesMax` | The same band as numbers, so it is filterable regardless of language |
| `industry`, `activities[]` | Kompass activity labels (short classification strings, not prose) |
| `naceCode` | The official activity code where the page publishes it — 4-digit NACE / NAF / ATECO, or a 5-digit national code (German WZ, e.g. `41102`) |
| `activityCode` | Kompass's own numeric activity code where the page exposes it |
| `foundedYear` | Year of incorporation |
| `vatNumber`, `registrationNumber` | VAT / tax ID and the local company register number where published |
| `description` | The company's own description text |
| `executives[]` | Named executives with role, where the page exposed them (gated on many pages) |
| `attributes{}` | Every other label→value row the page carried, verbatim and language-native |
| **`captureDate`**, **`captureYear`** | **The day this page was archived. Read it before you use the row.** |
| **`sourceArchive`** | `Internet Archive Wayback Machine` or `Common Crawl` |
| **`archiveUrl`** | Direct link to the archived page, so any row is independently verifiable |
| `sourceUrl` | The original Kompass URL the archive captured |
| `templateEra` | `legacy` (2014-2018 layout) or `modern` (2019+ layout) |
| `isArchivedSnapshot` | Always `true`. It is in every row on purpose. |

***

### ⚠️ Read this before you buy rows

Seven things that would otherwise turn into a refund request.

1. **This is not live data, and no input makes it live.** There is no fallback that hits
   kompass.com. `minCaptureYear: "2024"` gets you the freshest ~2-3% of the corpus; it does not
   get you today.

2. **There is no `revenue` field, and there never will be from this source.** Kompass gates the
   revenue band behind a login on **every era and every archive** — 0 of 208 measured pages carried
   it. Any tool promising you Kompass revenue bands is getting them somewhere else.

3. **`email` is effectively 0%.** Kompass sells the email; the public page does not carry it. If
   you need mailboxes, run the `domain` column through an email-finder.

4. **`executives` is good but not universal, and it is partly masked.** It measured **98%** on the
   2026-08-19 German run (57 of 58 rows) but as low as 12% on the Common Crawl sample of other
   countries. Kompass publishes the top executive's full name and masks the rest to initials
   ("Herr G. H."), so a row with four executives is usually one name plus three initials.

5. **This Actor uses Apify Proxy.** `web.archive.org` rate-limits by client IP and the shared IP of
   an Apify run container is permanently over that limit — a run without a proxy gets HTTP 429 on
   every request and returns nothing (measured 2026-08-19: two consecutive runs, 0 rows). Every
   archive request therefore goes through Apify Proxy on a rotating session, on the cheap datacenter
   lane. Proxy usage is billed by Apify at platform rates, not by this Actor.

6. **The index is alphabetical, so runs start at the top of the alphabet.** A second run with the
   same input returns the same companies. To walk deeper into a country, raise **Start at index
   page** (one page ≈ 1,700-4,100 companies, average 2,530) or use **Company name contains**.

7. **`nameContains` matches the company NAME, not the industry.** It filters on the company-name
   slug inside the archived URL, which is why it is free and instant. `"pharma"` finds companies
   with "pharma" in their name, not every pharmaceutical company.

***

### 💰 Pricing

**$0.002 per company returned. $2 per 1,000. No run-start fee, no per-page fee, no subscription.**

That is deliberately the cheapest Kompass row on the Apify Store — checked live on 2026-08-17
against `santamaria-automations/kompass-scraper` ($0.003 per search result **plus** $0.005 per full
profile **plus** $0.005 per run start), `scrapesage/kompass-scraper` ($0.003 per company plus
$0.006 for details) and `totaka/kompass-france-b2b-scraper` ($0.004 per result). It is cheaper
because **archived snapshots are worth less than live rows and the price should say so.**

Three things about how you are billed:

- Companies are **deduplicated on `kompassId` before anything is fetched**, so you never pay twice
  for the same company inside a run.
- A page that downloads but does not parse into a real company record is **never pushed and never
  charged**.
- The free **Coverage check** mode pushes its rows without the billing event, so it costs **$0**.

***

### ❓ FAQ

**Does this Actor ever touch kompass.com?**
No. There is a hard allowlist in the code — `web.archive.org`, `index.commoncrawl.org`,
`data.commoncrawl.org` — and every single HTTP request in the Actor goes through one function that
throws if the host is anything else. There is no proxy configuration, no CAPTCHA solver, and no
live fallback, by design.

**Why is Common Crawl an option if it only holds 161 companies?**
Because those 161 are the **freshest** records available anywhere in the archives (newest capture
2026-06-18), and 105 of them are not in the Wayback set at all. It is a small genuine complement,
not a substitute. `source: "both"` uses Wayback for volume and tops up from the 6 newest Common
Crawl indexes.

**Why is my run slow?**
On purpose. The Internet Archive soft-blocks under sustained hammering — empty 200s first, then
HTTP 429 — so index requests are spaced ~1.6s apart and page downloads are throttled and retried
with backoff. Each archived page is 250-460 KB. Budget roughly one to two seconds per company —
the same 150-row input has been measured at 158 s on a fast day and 298 s on a slow one, because
the archive's answering speed is not ours to control. Raising **Parallel archive requests** above
4 usually makes a run *slower*, not faster.

**What if archive.org refuses to answer the index?**
It rate-limits its CDX index hard — two runs in quick succession from the same IP can get `HTTP 429`
for a minute or two, even though the endpoint that serves the page bodies keeps answering normally.
The Actor retries patiently, and if the index still will not answer, an **unfiltered German request**
falls back to a bundled list of 260 real archived German captures harvested from the identical CDX
query on 2026-08-17, so the run still returns real rows and says so in the log. That fallback is
deliberately *not* used when you set a name keyword, a minimum capture year, a start page, pasted
URLs, or a country other than Germany — a filtered request must never be answered with rows that
ignore the filter. In that case the run ends successfully with an explanation and **charges nothing**.

**What if the archive is having a bad day and my run runs out of time?**
It still succeeds. The Actor derives a wall-clock budget from your run's own timeout, stops
starting new archive fetches when it hits it, flushes everything already collected to the dataset,
and exits **successfully** with a status message saying so — it never runs the clock out into a
TIMED-OUT run, and you are only ever charged for rows that were actually delivered. If you want a
big pull, raise **both** `maxCompanies` and the run timeout.

A default-sized run (60 companies or fewer, and the free coverage check) also carries an **absolute
195-second fetching cap** on top of that, whatever run timeout it was started with: a run that small
takes 120-165 s when the archive is healthy, so one still fetching at 195 s is the archive being
slow, not a bigger job. It stops, delivers what it has, and ends successfully. Ask for more than 60
companies and the cap does not apply — a big pull gets the full run timeout.

**How short can the run timeout be?** 30 seconds of any run is held back to deliver the rows already
collected and finish cleanly, so the fetching budget is *your timeout minus 30 s*. A run started with
35 s or less has nothing left to fetch in: it stops in about 2 s, delivers nothing, charges nothing,
and says so in its status message rather than dying. Below about 60 s you will get very few rows —
reading one archive index page alone measures ~35 s. **Use 300 s or more.** A default-sized run
measures 66-190 s end to end.

**Two runs — will I get duplicates?**
Within a run, no: dedupe happens on `kompassId` before fetching, and a 150-row run measured
**0 duplicates**. Across runs there is no memory, so the same input returns the same
companies. Diff on `kompassId`, or move **Start at index page** forward.

**A country I want is not in the enumerated table. Is it empty?**
No — it just was not counted yet. All 62 country hosts are selectable. Run the free **Coverage
check** first to see how deep the archive goes for it.

**Will a run ever succeed with zero rows?**
Only when the archive genuinely holds nothing for your filter — for example a rare keyword plus
`minCaptureYear: 2024`. That exits **cleanly** with a log line telling you which filter to loosen,
and charges nothing. A run that is actually **broken** — the archive is down, or the page template
changed under the parser — **fails loudly** with an error that says which of the two it was.

**Can I verify a row myself?**
Yes, and you should spot-check a few. Every row carries `archiveUrl`. Open it and you are looking
at the same archived page the Actor parsed, hosted by the Internet Archive.

**Can I get the whole 828k corpus?**
Yes — set `maxCompanies` high and let it run, or chain runs per country with **Start at index
page**. At $0.002 the full measured corpus is about $1,656. Mind the run timeout (the Actor ships
with 2 hours; raise it for large sweeps).

***

### ⚖️ Legal and fair use

This Actor reads **public web archives**. It does not log in, does not solve CAPTCHAs, does not use
proxies, and never sends a request to the source site.

Four things to know and judge for yourself:

1. **`kompass.com`'s own `robots.txt` disallows `/c/`** — the company detail path — for all
   user-agents. That is why Common Crawl's crawler is blocked there today, and it is a real
   consideration. The archives hold historical captures of those pages regardless. This is a
   terms-of-service question, not a technical one, and it is yours to weigh. *(Quoted from the copy
   of `robots.txt` that Common Crawl captured on 2026-07-16.)*
2. **Common Crawl's Terms of Use** (last updated **7 March 2024**) grant "a limited,
   non-assignable, non-transferable, non-sublicensable, non-exclusive, limited license to access
   and use the Service", and state that Crawled Content "may be subject to separate terms of use or
   terms of service from the owners of such Crawled Content." They also expressly prohibit using
   the Service for "displaying, distributing or transmitting unsolicited advertisements, promotional
   materials, 'spam'…" and for "collecting or harvesting any personally identifiable information or
   personal information for use separately from the Crawled Content." The `executives` field carries
   people's names; if that clause matters to your use case, leave `source` on the default
   `wayback` and drop the column.
3. **However you obtain business data, you remain responsible for marketing and anti-spam law** —
   GDPR, PECR, CAN-SPAM, CASL, TCPA — when you contact anyone on the list. Rows describe
   **businesses**, but a sole trader's business phone or address can also be personal data in some
   jurisdictions; treat the output accordingly.
4. **Accuracy.** Common Crawl's terms state plainly that they "cannot guarantee the truthfulness,
   authenticity, quality, lawfulness or accuracy of the Crawled Content." Neither can this Actor.
   What it does guarantee is that `captureDate` tells you exactly how old each row is, and
   `archiveUrl` lets you check it yourself.

KOMPASS® is a trademark of its owner. This Actor is not affiliated with, endorsed by, or sponsored
by Kompass International, the Internet Archive, or the Common Crawl Foundation.

***

### 📝 Changelog

| Date | Change |
|---|---|
| **2026-08-28** (0.1.19) | **Short run timeouts no longer end TIMED-OUT.** Measured before the fix, on identical inputs: 13 of 22 runs started with a timeout of 45 s or less ended TIMED-OUT with zero rows delivered and a blank status message — 8 of 8 at 35 s. Four independent causes, all fixed: a 30-second floor under the fetching budget handed back the reserve that was supposed to pay for delivery; each request was given its timeout *before* the politeness sleeps, so it could overshoot its own deadline by 11-15 s; nothing cancelled in-flight requests when the budget expired, so the run waited on wedged sockets instead of delivering (measured: 11.3 s of silence, then the kill); and rows were only pushed once 20 had accumulated, so a kill cost the whole run. Now every request carries a cancel signal, rows are pushed every 10 rows **or every 20 seconds**, the status message is written *before* the final push, and the run force-exits successfully with time to spare rather than being killed. After the fix: **0 TIMED-OUT runs in 42**, including 31 at 45 s or less. Same-moment A/B against the old build on the long path shows no loss: 60/60 rows at 300 s on both. Default memory restored 512 MB → 1024 MB (measured on the same input at the same moment: 95 s vs 158 s for the same 60 rows). |
| **2026-08-20** (0.1.12) | Close-out audit. **Four classification/VAT fields were being read on only one of the two page templates** — fixed against 62 re-downloaded archived bodies: `naceCode` 15% → 81%, `activityCode` 29% → 100%, `industry` 53% → 87%, `activities` 53% → 92%, `vatNumber` 58% → 79% (legacy pages publish the official codes in a separate `Andere Klassifikationen` block and the Kompass activity code as the activity-tree anchor id; modern pages nest a hidden "call this company" modal inside the VAT cell, which used to make the whole row unreadable). `industry` now ships empty rather than shipping marketing prose. **Billing:** the charge result now gates the loop — a run that reaches its maximum total charge stops on a whole row with a plain-English message, and delivered rows and billed rows are always the same set (proved: a $0.05-capped run delivered 26 rows and billed exactly 26). Default memory lowered 1024 MB → 512 MB after measuring peak usage at 191 MB, which halves the compute you pay for on every run. |
| **2026-08-17** (0.1.3) | Adversarial audit pass. Run statistics (field fill, capture-year histogram, template era) are now counted on the rows that were actually **delivered and charged**, not on the wider set that was parsed and trimmed. `Company name contains` is now applied to Common Crawl candidates too — it used to be silently ignored on that source. Corpus-size estimates re-derived from measured index-page density (1,725-4,087 per page, average 2,530) instead of a flat 2,800. Coverage check now labels every row `measured-live` vs cached, stops hammering archive.org after 5 refusals, and streams rows as it goes. A Common Crawl index outage now fails loudly instead of looking like an empty archive. README numbers re-counted against three platform runs. |
| **2026-08-17** | First release. Archive route measured end to end: 828,183 archived company pages counted across 12 Wayback country hosts, 208 archived bodies downloaded and parsed at 99%, staleness measured directly (2.5-2.9% of the corpus captured 2024+). Dual-era parser (2014-2018 and 2019+ templates), geo-coordinates and numeric employee bands added, free country-coverage mode, hard archive-only host allowlist. |

***

### 💬 Support

Missing a country, want a filter that isn't here, or found a field the parser is leaving on the
page? **Open an issue on the Issues tab** — it gets read, and the archive gets re-measured.

If this saved you a week of fighting an anti-bot wall, **a 5-star rating helps other people find
it**.

***

**Keywords:** kompass scraper · kompass b2b · kompass company data · kompass directory export ·
b2b company database · european company database · b2b lead list · firmographic data · company
firmographics · industrial supplier list · manufacturer database · B2B TAM list · total addressable
market data · CRM enrichment · company enrichment · VAT number lookup · company registration number
· employee band data · company geo-coordinates · business address database · german company data ·
italian company data · spanish company data · polish company data · french company data · uk
company data · dutch company data · belgian company data · chinese supplier list · indian
manufacturer list · taiwan supplier list · us company database · archived web data · wayback
machine dataset · common crawl dataset · web archive scraper · historical company data · supplier
prospecting · procurement supplier discovery · export import leads · manufacturing leads ·
wholesale supplier leads · sales prospecting list · outbound lead list · account-based marketing
list · data enrichment source · company matching · entity resolution

# Actor input Schema

## `listCountries` (type: `boolean`):

Tick this and the run skips scraping entirely: it returns one row per Kompass country host (62 rows) with the number of index pages the Wayback Machine holds for it, an estimated company count, and — for the 12 hosts that were exhaustively enumerated — the exact measured count. These rows are pushed WITHOUT the billing event, so a coverage run costs $0 in Actor charges. Two honest caveats: it takes a few minutes because archive.org rate-limits its index endpoint, and when archive.org is refusing requests (HTTP 429) the run stops re-counting after 5 refusals and reports the 2026-08-16 enumeration instead — the indexStatus column on every row says whether that row was counted live or comes from the cached enumeration. Then untick it and run for real.

## `countries` (type: `array`):

Which countries' companies to pull, by ISO 2-letter code. The counts in brackets are archived pages on that country's Kompass host (92-98% of them carry that country's ID prefix; the rest are companies cross-listed from elsewhere). This is matched against the Kompass company ID prefix, which is the company's real country — Kompass country sites cross-serve each other's records, so the site you would have browsed is not a reliable country filter and is not used as one here. Leave the default (Germany) for a first run.

## `nameContains` (type: `array`):

Keep only companies whose name contains one of these words. Matched against the company-name slug inside the archived URL, so it is fast and costs nothing extra — but it matches the NAME, not the industry. Good: 'gmbh', 'logistik', 'pharma', 'steel', 'transport'. Several words are OR-ed together. Leave empty to walk the country alphabetically.

## `companyUrls` (type: `array`):

Paste full Kompass company URLs (https://de.kompass.com/c/some-company/de664484/) or bare Kompass IDs (DE664484, NLC0733131). Each one is looked up in the Wayback index and pulled from the archive. Anything you paste is fetched in addition to the country walk above.

## `source` (type: `string`):

wayback = volume (recommended, and what the defaults use). commoncrawl = the ~161 freshest records only, mostly 2023-2026 captures. both = Wayback first, topped up from the 6 newest Common Crawl indexes.

## `minCaptureYear` (type: `string`):

This is the freshness dial, and it does two things. Each row is the EARLIEST archived capture of that company's page on or after the year you pick — so on 'any' you get each page's oldest snapshot (mostly 2014-2018), and raising the year pulls a LATER capture of the same companies, at the cost of dropping every company the archive has not re-captured since. Measured 2026-08-17: 2.5-2.9% of archived pages carry a 2024-or-later capture (tw 441/17,396, nl 970/32,832). Rows always carry captureDate so you can filter afterwards too.

## `startPage` (type: `integer`):

The archive index is ordered alphabetically by company name, so a run always starts at the beginning of the alphabet. Raise this to walk deeper into a country without repeating rows you already bought (one index page is roughly 2,000-2,800 companies).

## `maxCompanies` (type: `integer`):

Hard cap on billed rows. The prefilled 60 costs $0.12 at $0.002 per company and finishes in roughly 1-2 minutes — it is a deliberately small first click, not a ceiling. Raise it to whatever you need (up to 100,000) and raise the run timeout with it: archived pages are 250-460 KB each and the archives are rate-limited on purpose, so budget roughly 1-2 seconds per company. If a run reaches its timeout budget it stops fetching, delivers everything already collected, and ends successfully — you are never charged for rows you did not get.

## `strictCountry` (type: `boolean`):

ON (recommended): drop any company whose Kompass ID prefix is not one of the countries you picked. Kompass country sites carry each other's records, so leaving this off returns neighbours you did not ask for. Turn it off only if you want everything the archive holds for those hosts.

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

How many archived pages to download at once. The Internet Archive soft-blocks under sustained hammering (empty 200s, then HTTP 429), so 4 is the tested setting. Raise it only if you accept slower, retried runs.

## Actor input object example

```json
{
  "listCountries": false,
  "countries": [
    "DE"
  ],
  "nameContains": [],
  "companyUrls": [],
  "source": "wayback",
  "minCaptureYear": "any",
  "startPage": 0,
  "maxCompanies": 60,
  "strictCountry": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `items` (type: `string`):

One row per company, reconstructed from a public web-archive capture: kompassId, name, country, city, address, phone, website, employee band, geo-coordinates, activities — plus captureDate and sourceArchive so you always know how old the row is.

# 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 = {
    "listCountries": false,
    "countries": [
        "DE"
    ],
    "nameContains": [],
    "companyUrls": [],
    "source": "wayback",
    "minCaptureYear": "any",
    "startPage": 0,
    "maxCompanies": 60,
    "strictCountry": true,
    "maxConcurrency": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/kompass-b2b-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 = {
    "listCountries": False,
    "countries": ["DE"],
    "nameContains": [],
    "companyUrls": [],
    "source": "wayback",
    "minCaptureYear": "any",
    "startPage": 0,
    "maxCompanies": 60,
    "strictCountry": True,
    "maxConcurrency": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/kompass-b2b-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 '{
  "listCountries": false,
  "countries": [
    "DE"
  ],
  "nameContains": [],
  "companyUrls": [],
  "source": "wayback",
  "minCaptureYear": "any",
  "startPage": 0,
  "maxCompanies": 60,
  "strictCountry": true,
  "maxConcurrency": 4
}' |
apify call scrapersdelight/kompass-b2b-scraper --silent --output-dataset

```

## MCP server setup

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