# Krak.dk Business Directory Scraper (`crawlerbros/krak-scraper`) Actor

Scrape Krak.dk, Denmark's leading business and phone directory. Search by keyword, browse by category and kommune (municipality), or fetch business detail pages directly. Get name, address, phone, email, website, CVR number, opening hours area, rating, and more - no login required.

- **URL**: https://apify.com/crawlerbros/krak-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Krak.dk Business Directory Scraper

Scrape [Krak.dk](https://www.krak.dk), Denmark's leading business and phone directory. Search any keyword, browse by category and kommune (municipality), or fetch specific business detail pages — no login, no cookies, no API key required.

### What this actor does

- **Three modes:** `search` (free-text, e.g. "restaurant København"), `byCategory` (browse a curated category + one of Denmark's 98 kommuner, or nationwide), `byUrl` (fetch specific business detail pages)
- **Rich business data:** name, categories, full address (street/postal code/city), GPS coordinates, phone, email, website, CVR number (Danish company registration ID), founding date, employee count, rating and review count
- **Nationwide coverage for category browsing:** `byCategory` without a specific kommune automatically shards the browse across all 98 Danish municipalities to reach higher `maxItems` values, working around Krak.dk's ~25-results-per-query page cap (see Limitations)
- **Filters:** location text filter (city/postal code/kommune), minimum rating, free-text keyword filter
- **Empty fields are omitted** — every record only contains data actually found for that business
- **Full Danish UTF-8 support** — city names, addresses, and descriptions preserve Danish characters exactly (København, Æbeltoft, Ålborg-style spellings, etc.)

### Output per business

- `businessId`, `sourceUrl` — unique numeric ID and canonical Krak.dk detail-page URL
- `name`
- `categories[]` — trade/branche tags (e.g. `Restaurant`, `Café`) *(richer when `fetchDetails: true`)*
- `businessType` — schema.org business type from the listing card (e.g. `Restaurant`, `BarOrPub`) *(listing-only, omitted once `categories` is available from the detail page)*
- `street`, `postalCode`, `city`, `fullAddress`
- `latitude`, `longitude` *(detail only)*
- `phone`, `email` *(detail only)*, `website` *(detail only — the business's own external site, not a krak.dk link)*
- `socialLinks[]` — social media / external profile URLs (e.g. Facebook, Instagram) published on the business's profile *(detail only, when published)*
- `mapUrl` — Krak.dk's map link for the business *(detail only)*
- `cvrNumber` — Danish company registration number (CVR) *(detail only)*
- `foundingDate` — ISO `YYYY-MM-DD` *(detail only, when published)*
- `numberOfEmployees` *(detail only, when published)*
- `rating` (0-5), `reviewCount` *(detail only, when the business has reviews)*
- `description` *(detail only, when published)*
- `recordType: "business"`, `scrapedAt`

*(detail only)* fields are populated when `fetchDetails: true` (opt-in for `search`/`byCategory` — off by default, see Limitations) or always for `mode: byUrl`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byCategory` / `byUrl` |
| `searchQuery` | string | `restaurant København` | Free-text query combining a category/trade and a place, exactly like Krak's own search bar (mode=search) |
| `category` | string (enum) | `Restaurant` | One of ~62 curated categories (mode=byCategory) |
| `customCategory` | string | – | Free-text category override, used instead of `category` (mode=byCategory) |
| `kommune` | string (enum) | – | One of Denmark's 98 kommuner (mode=byCategory); leave empty for a nationwide, auto-sharded browse |
| `location` | string | – | Free-text place (city/kommune/postal code). Combined into the query for `search`/`byCategory`, and applied everywhere as a safety-net filter |
| `urls` | array | – | Krak.dk detail-page URLs (mode=byUrl) |
| `keyword` | string | – | Keep only results whose name/description/categories contain this text |
| `minRating` | number | – | Drop businesses rated below this (0-5); only applies once `fetchDetails` has populated `rating` |
| `fetchDetails` | boolean | `false` | Visit each business's detail page for email/website/CVR/founding date/employee count/geo/rating/description (1 extra Playwright page load per business, several seconds each; best-effort — see Limitations) |
| `maxItems` | integer | `25` | Hard cap (1-300) |
| `proxyConfiguration` | object | – | Optional; Krak.dk works without a proxy, the actor auto-escalates to the free AUTO group on a persistent 403/429 |

#### Example: search by keyword + place

```json
{
  "mode": "search",
  "searchQuery": "VVS Vanløse",
  "maxItems": 25
}
````

#### Example: browse a category within one kommune

```json
{
  "mode": "byCategory",
  "category": "Frisør",
  "kommune": "Odense",
  "fetchDetails": true,
  "maxItems": 50
}
```

#### Example: browse a category nationwide (auto-sharded across kommuner)

```json
{
  "mode": "byCategory",
  "category": "Tandlæge",
  "maxItems": 200
}
```

#### Example: fetch specific business pages

```json
{
  "mode": "byUrl",
  "urls": [
    "https://www.krak.dk/caf%C3%A9+zirup+k%C3%B8benhavn+k/67493772/firma"
  ]
}
```

### Limitations

- **Krak.dk requires a real browser (Cloudflare Turnstile).** Krak.dk fronts every page with Cloudflare's JS challenge (`cf-mitigated: challenge`, "Just a moment..."). A plain HTTP client (even one impersonating a full Chrome TLS fingerprint) can never pass this — it requires executing real JavaScript — so this actor drives a headless, stealth-configured Chromium browser (Playwright) for every request. No proxy is used by default (a residential/datacenter proxy round-trip was tested and made no difference to whether the challenge passed, and Apify's free AUTO datacenter proxy group timed out entirely against krak.dk in testing).
- **Detail-page enrichment (`fetchDetails: true`) is best-effort and can be rate-blocked mid-run.** krak.dk's anti-bot layer tolerates a limited burst of detail-page requests per run/IP and then escalates to a hard (non-challenge) 403 for further detail-page requests for a cooldown period; it does **not** rate-block the listing/search pages themselves. The actor detects this automatically (a circuit breaker disables further detail fetches after 5 consecutive failures) and falls back to listing-only data for the rest of the run rather than failing or hanging — so a run always completes and always returns real data, but the richer detail-only fields (`email`, `website`, `cvrNumber`, `foundingDate`, `numberOfEmployees`, `latitude`/`longitude`, `rating`, `reviewCount`, full `categories`) may be present on some, all, or none of a run's records depending on current anti-bot conditions. Because of this, `fetchDetails` defaults to **off** — the default run only uses the always-reliable listing data (name, address, phone, `businessType`) — and detail enrichment is an explicit opt-in for users who want the richer fields and can tolerate partial coverage under heavy load.
- **~25 results per single Krak.dk query.** Krak.dk's listing pages are server-rendered with exactly one page of results (25 items) embedded in their JSON-LD `ItemList` — no working `page=`/`offset=`/cursor parameter exists (confirmed by testing multiple variants against the live site; all return the identical first page). This is an upstream limit, not an actor bug. `mode: byCategory` without a specific `kommune`/`location` works around it by automatically shard-querying across all 98 kommuner (deduplicated by business ID) to reach higher `maxItems` values; `mode: search` and a location-scoped `byCategory` query are capped at ~25 results by design.
- **Opening hours are not exposed.** Krak.dk's own detail pages did not expose a reliable, structured per-business opening-hours field in JSON-LD or DOM during research (only Krak's own customer-service hours were found) — this field is intentionally omitted rather than shipping guessed or inconsistent data.
- **`rating`/`reviewCount`/`categories` (beyond the listing card's coarse `businessType`)/`email`/`website`/`cvrNumber`/`foundingDate`/`numberOfEmployees`/geo-coordinates require `fetchDetails: true` and available detail-page budget** (or `mode: byUrl`, which always attempts the detail page) — they live only on the detail page, not the listing card.

### Use cases

- **Lead generation** — build lists of Danish businesses by trade category and kommune
- **Local SEO & marketing agencies** — audit a client's phone/email/website presence on Denmark's leading directory
- **Market research** — measure business density and category coverage across Danish municipalities
- **Data enrichment** — attach CVR numbers, coordinates, and contact details to an existing company dataset
- **Competitive analysis** — track ratings and review counts for a category (e.g. restaurants, hairdressers) in a given city

### FAQ

**Do I need a proxy or login?** No. Krak.dk is scraped directly with no cookies, no API key, and no Apify proxy required by default.

**Why do some businesses have far more fields than others?** Krak.dk only publishes what each business itself has completed on its profile (website, email, CVR, rating, etc.) — the actor never fabricates missing data; empty fields are simply omitted from that record.

**Can I search for a business by name?** Yes — use `mode: search` with the business name as `searchQuery` (optionally add a place, e.g. `"Netto København"`), or use `mode: byUrl` if you already have its Krak.dk profile link.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text keyword combining a category/trade and (optionally) a place, exactly like Krak's own search bar, e.g. "restaurant København", "VVS Vanløse", "pizza Odense", or just a business name.

## `category` (type: `string`):

A curated Krak.dk category/branche. Combine with `kommune` to scope to one municipality, or leave `kommune` empty for a nationwide browse (auto-sharded across all 98 kommuner up to `maxItems`).

## `customCategory` (type: `string`):

Type any category/branche text not in the curated dropdown (e.g. "Vinhandel"). Overrides `category` when set.

## `kommune` (type: `string`):

Restrict the category browse to one of Denmark's 98 kommuner. Leave empty for a nationwide browse (auto-sharded across all kommuner up to `maxItems`).

## `location` (type: `string`):

Free-text place name (city, kommune, postal code). For mode=search/byCategory it's combined into the Krak.dk query text; for all modes it's also applied as a client-side safety-net filter on the resulting city/postal code/address.

## `urls` (type: `array`):

Full krak.dk detail-page URLs, e.g. `https://www.krak.dk/caf%C3%A9+zirup+k%C3%B8benhavn+k/67493772/firma`.

## `keyword` (type: `string`):

Only keep results whose name, description, or categories contain this text (case- and diacritics-insensitive).

## `minRating` (type: `number`):

Drop businesses with a review rating below this value. Only meaningful when `fetchDetails` is on (rating is a detail-page field) — records without a rating always pass through.

## `fetchDetails` (type: `boolean`):

Visit each business's detail page to also collect email, website, CVR number, founding date, employee count, GPS coordinates, rating/review count, and description. Adds one extra Playwright page load per business (several seconds each). Best-effort: Krak.dk's anti-bot protection can rate-block a burst of detail-page requests from the same IP mid-run — the actor detects this automatically and falls back to listing-only data for the rest of the run rather than failing (see README Limitations). Defaults to off so the base run is always fast and fully reliable; turn on when you need the richer fields and can tolerate a partial fallback under heavy load.

## `maxItems` (type: `integer`):

Hard cap on emitted records. Note: a single Krak.dk query returns at most ~25 results (no working pagination was found upstream); mode=byCategory without a `kommune`/`location` auto-shards across all 98 kommuner to reach higher values. Each business detail fetch (when `fetchDetails` is on) takes several seconds due to Krak.dk's anti-bot challenge — keep this modest (10-30) for fast runs; larger values still work, just take longer.

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

Optional proxy settings. Leave empty to use no proxy — Krak.dk is reachable directly via the actor's browser-impersonating HTTP client. The actor automatically escalates to the free AUTO datacenter proxy group if it hits a persistent 403/429.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "restaurant København",
  "category": "Restaurant",
  "kommune": "",
  "urls": [],
  "fetchDetails": false,
  "maxItems": 25
}
```

# Actor output Schema

## `businesses` (type: `string`):

Dataset containing all scraped Krak.dk businesses.

# 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 = {
    "mode": "search",
    "searchQuery": "restaurant København",
    "category": "Restaurant",
    "kommune": "",
    "urls": [],
    "fetchDetails": false,
    "maxItems": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/krak-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 = {
    "mode": "search",
    "searchQuery": "restaurant København",
    "category": "Restaurant",
    "kommune": "",
    "urls": [],
    "fetchDetails": False,
    "maxItems": 25,
}

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

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

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

```

## CLI example

```bash
echo '{
  "mode": "search",
  "searchQuery": "restaurant København",
  "category": "Restaurant",
  "kommune": "",
  "urls": [],
  "fetchDetails": false,
  "maxItems": 25
}' |
apify call crawlerbros/krak-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/krak-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Krak.dk Business Directory Scraper",
        "description": "Scrape Krak.dk, Denmark's leading business and phone directory. Search by keyword, browse by category and kommune (municipality), or fetch business detail pages directly. Get name, address, phone, email, website, CVR number, opening hours area, rating, and more - no login required.",
        "version": "1.0",
        "x-build-id": "57Wegzki1B8vJELWm"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~krak-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-krak-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/crawlerbros~krak-scraper/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-krak-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/crawlerbros~krak-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-krak-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "byCategory",
                            "byUrl"
                        ],
                        "type": "string",
                        "description": "What to fetch.",
                        "default": "search"
                    },
                    "searchQuery": {
                        "title": "Search query (mode=search)",
                        "type": "string",
                        "description": "Free-text keyword combining a category/trade and (optionally) a place, exactly like Krak's own search bar, e.g. \"restaurant København\", \"VVS Vanløse\", \"pizza Odense\", or just a business name.",
                        "default": "restaurant København"
                    },
                    "category": {
                        "title": "Category (mode=byCategory)",
                        "enum": [
                            "Restaurant",
                            "Café",
                            "Pizzeria",
                            "Bar",
                            "Hotel",
                            "Frisør",
                            "Skønhedsklinik",
                            "Massageklinik",
                            "Fysioterapeut",
                            "Kiropraktor",
                            "Tandlæge",
                            "Læge",
                            "Apotek",
                            "Dyrlæge",
                            "Psykolog",
                            "Fodterapeut",
                            "Fitnesscenter",
                            "VVS",
                            "Elektriker",
                            "Tømrer",
                            "Murer",
                            "Malere",
                            "Snedker",
                            "Elinstallatør",
                            "Glarmester",
                            "Tagdækker",
                            "Anlægsgartner",
                            "Gartner",
                            "Skadedyrsbekæmpelse",
                            "Rengøring",
                            "Flyttefirma",
                            "Autoværksted",
                            "Bilvask",
                            "Biludlejning",
                            "Autoophug",
                            "Taxi",
                            "Vognmænd",
                            "Chauffør",
                            "Entreprenør",
                            "Byggemarked",
                            "Møbelforretning",
                            "Tøjbutik",
                            "Skobutik",
                            "Guldsmed",
                            "Optiker",
                            "Blomsterbutik",
                            "Dyrehandel",
                            "Boghandel",
                            "Bager",
                            "Slagter",
                            "Supermarked",
                            "Dagligvarebutik",
                            "Advokat",
                            "Revisor",
                            "Ejendomsmægler",
                            "Forsikring",
                            "Bank",
                            "Rejsebureau",
                            "Bedemænd",
                            "Vuggestue",
                            "Sprogskole",
                            "Låsesmed",
                            "Skorstensfejer"
                        ],
                        "type": "string",
                        "description": "A curated Krak.dk category/branche. Combine with `kommune` to scope to one municipality, or leave `kommune` empty for a nationwide browse (auto-sharded across all 98 kommuner up to `maxItems`).",
                        "default": "Restaurant"
                    },
                    "customCategory": {
                        "title": "Custom category override (mode=byCategory)",
                        "type": "string",
                        "description": "Type any category/branche text not in the curated dropdown (e.g. \"Vinhandel\"). Overrides `category` when set."
                    },
                    "kommune": {
                        "title": "Kommune / municipality (mode=byCategory)",
                        "enum": [
                            "",
                            "Albertslund",
                            "Allerød",
                            "Ballerup",
                            "Bornholm",
                            "Brøndby",
                            "Dragør",
                            "Egedal",
                            "Fredensborg",
                            "Frederiksberg",
                            "Frederikssund",
                            "Furesø",
                            "Gentofte",
                            "Gladsaxe",
                            "Glostrup",
                            "Gribskov",
                            "Halsnæs",
                            "Helsingør",
                            "Herlev",
                            "Hillerød",
                            "Hvidovre",
                            "Høje-Taastrup",
                            "Hørsholm",
                            "Ishøj",
                            "København",
                            "Lyngby-Taarbæk",
                            "Rudersdal",
                            "Rødovre",
                            "Tårnby",
                            "Vallensbæk",
                            "Faxe",
                            "Greve",
                            "Guldborgsund",
                            "Holbæk",
                            "Kalundborg",
                            "Køge",
                            "Lejre",
                            "Lolland",
                            "Næstved",
                            "Odsherred",
                            "Ringsted",
                            "Roskilde",
                            "Slagelse",
                            "Solrød",
                            "Sorø",
                            "Stevns",
                            "Vordingborg",
                            "Assens",
                            "Billund",
                            "Esbjerg",
                            "Fanø",
                            "Fredericia",
                            "Faaborg-Midtfyn",
                            "Haderslev",
                            "Kerteminde",
                            "Kolding",
                            "Langeland",
                            "Middelfart",
                            "Nordfyns",
                            "Nyborg",
                            "Odense",
                            "Svendborg",
                            "Sønderborg",
                            "Tønder",
                            "Varde",
                            "Vejen",
                            "Vejle",
                            "Ærø",
                            "Aabenraa",
                            "Favrskov",
                            "Hedensted",
                            "Herning",
                            "Holstebro",
                            "Horsens",
                            "Ikast-Brande",
                            "Lemvig",
                            "Norddjurs",
                            "Odder",
                            "Randers",
                            "Ringkøbing-Skjern",
                            "Samsø",
                            "Silkeborg",
                            "Skanderborg",
                            "Skive",
                            "Struer",
                            "Syddjurs",
                            "Viborg",
                            "Aarhus",
                            "Brønderslev",
                            "Frederikshavn",
                            "Hjørring",
                            "Jammerbugt",
                            "Læsø",
                            "Mariagerfjord",
                            "Morsø",
                            "Rebild",
                            "Thisted",
                            "Vesthimmerland",
                            "Aalborg"
                        ],
                        "type": "string",
                        "description": "Restrict the category browse to one of Denmark's 98 kommuner. Leave empty for a nationwide browse (auto-sharded across all kommuner up to `maxItems`).",
                        "default": ""
                    },
                    "location": {
                        "title": "Location filter (all modes)",
                        "type": "string",
                        "description": "Free-text place name (city, kommune, postal code). For mode=search/byCategory it's combined into the Krak.dk query text; for all modes it's also applied as a client-side safety-net filter on the resulting city/postal code/address."
                    },
                    "urls": {
                        "title": "Business detail URLs (mode=byUrl)",
                        "type": "array",
                        "description": "Full krak.dk detail-page URLs, e.g. `https://www.krak.dk/caf%C3%A9+zirup+k%C3%B8benhavn+k/67493772/firma`.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "keyword": {
                        "title": "Keyword filter",
                        "type": "string",
                        "description": "Only keep results whose name, description, or categories contain this text (case- and diacritics-insensitive)."
                    },
                    "minRating": {
                        "title": "Minimum rating (0-5)",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Drop businesses with a review rating below this value. Only meaningful when `fetchDetails` is on (rating is a detail-page field) — records without a rating always pass through."
                    },
                    "fetchDetails": {
                        "title": "Fetch full detail page per business",
                        "type": "boolean",
                        "description": "Visit each business's detail page to also collect email, website, CVR number, founding date, employee count, GPS coordinates, rating/review count, and description. Adds one extra Playwright page load per business (several seconds each). Best-effort: Krak.dk's anti-bot protection can rate-block a burst of detail-page requests from the same IP mid-run — the actor detects this automatically and falls back to listing-only data for the rest of the run rather than failing (see README Limitations). Defaults to off so the base run is always fast and fully reliable; turn on when you need the richer fields and can tolerate a partial fallback under heavy load.",
                        "default": false
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 300,
                        "type": "integer",
                        "description": "Hard cap on emitted records. Note: a single Krak.dk query returns at most ~25 results (no working pagination was found upstream); mode=byCategory without a `kommune`/`location` auto-shards across all 98 kommuner to reach higher values. Each business detail fetch (when `fetchDetails` is on) takes several seconds due to Krak.dk's anti-bot challenge — keep this modest (10-30) for fast runs; larger values still work, just take longer.",
                        "default": 25
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional proxy settings. Leave empty to use no proxy — Krak.dk is reachable directly via the actor's browser-impersonating HTTP client. The actor automatically escalates to the free AUTO datacenter proxy group if it hits a persistent 403/429."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
