# Firmy.cz Scraper (`solidcode/firmy-search-scraper`) Actor

\[💰 $4.0 / 1K] Extract Czech business listings from Firmy.cz — name, address, phone, website, email, rating, opening hours, IČO, photos, geo coordinates, and more. Search by keyword + city, browse by category, or paste Firmy.cz URLs directly.

- **URL**: https://apify.com/solidcode/firmy-search-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 62 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 results

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

## Firmy.cz Scraper

Pull Czech business listings from Firmy.cz at scale — names, addresses, phone numbers, websites, ratings, opening hours, geo coordinates, IČO, Datová schránka, and photo galleries for 750,000+ verified businesses across all 12 Seznam.cz top-level categories. Built for Czech B2B sales teams, EU market-entry consultants, and CRM data engineers who need clean, structured firmy.cz data without parsing HTML and chasing consent gates themselves.

### Why This Scraper?

- **True category browsing, not keyword guessing** — pick any of firmy.cz's 12 top-level categories (Restaurants, Auto & Motoring, Electronics, Shops, Services & Trades, Home & Garden, Healthcare, Banks & Finance, Travel, Government, Business Services, Wholesale & Manufacturing) plus the Beauty & Body Care section, and you get exactly the businesses firmy.cz files there. A keyword search for "elektro" also drags in electricians; the Electronics category does not.
- **IČO and Datová schránka extraction** — every detail-enriched record carries the Czech business ID and the official electronic mailbox identifier required for B2B compliance, invoicing, and government correspondence.
- **33 fields per business** — name, full address breakdown (street, city, postal code), latitude/longitude, phone, email, website, rating (0–5) on Seznam's own scale, review count, one-line opening summary, full weekly schedule, logo, gallery, social links, amenities, Seznam's own “Verified business” and “TOP FIRMA” award flags, short description, optional reservation link, IČO, Datová schránka, and a stable `premiseId` for cross-run deduplication.
- **4 input modes** — free-text keyword, keyword + Czech city, category browse, or paste any firmy.cz search URL directly. Mix and match in a single run.
- **Diacritic-safe Czech UTF-8** — names like "Lékárna U Černého orla" and "Žižkov" pass through input, pagination, and output cleanly. Tested on `č ž ř ě ů á í é ý`.
- **Verified at full scale, and your limit is exact** — 1,362 rows from a single `lekárna Olomouc` query in 4.5 minutes. Ask for 200 and you get 200, never 210: surplus listings from the final page are dropped before billing.
- **Optional detail enrichment** — one toggle adds IČO, Datová schránka, business email, the complete 7-day opening-hours table, social media links, amenities, the full description, and up to ~28 photos per business. Descriptions and amenity tags arrive in English; every other field keeps its original Czech.
- **City-level geo scoping built in** — Czech cities, districts (`okres`), and regions (`kraj`) are auto-resolved to the correct firmy.cz scope through Seznam's own region geocoder, so "Praha", "Brno-venkov", and "Jihomoravský kraj" all just work.
- **Unlimited mode** — set Max Results to `0` to pull every available listing for a query (internal safety cap of 50,000 prevents runaway pagination).

### Use Cases

**Czech Market Entry & Lead Generation**

- Build a national prospect list of pharmacies, dental clinics, or auto-services with phone, email, and IČO ready for cold outreach
- Extract verified contact info for every restaurant in a target Czech city before launching a delivery or POS product
- Pull complete supplier directories by category for procurement teams expanding into Czechia

**B2B Compliance & KYC**

- Capture IČO and Datová schránka identifiers required for Czech invoicing, contract enforcement, and government filings
- Cross-reference business names against the Czech business register for due diligence
- Maintain up-to-date supplier records with verified addresses and contact channels

**Local SEO & Reputation Monitoring**

- Track how your business and competitors rank inside firmy.cz category and city listings
- Monitor review counts and rating trends across the Czech market over time
- Audit your own listing fields (logo, photos, hours, website) against the public profile

**Market Research & Competitive Analysis**

- Map business density by Czech district to spot underserved categories
- Compare opening hours, ratings, and amenities across regional competitor sets
- Identify category leaders by review volume in any Czech city or region

**Data Enrichment**

- Append phone, email, geo coordinates, and IČO to existing CRM records keyed by business name and city
- Hydrate Czech business directories with structured rating and category data
- Power Czech-language map products with Seznam-grade business metadata

### Getting Started

#### Search by Keyword

Just a Czech keyword — searches all of Czech Republic:

```json
{
    "searchQuery": "restaurace",
    "maxResults": 50
}
```

#### Keyword + City

Scope a search to a single Czech city. The city name is auto-resolved through Seznam's geocoder:

```json
{
    "searchQuery": "zubař",
    "location": "Praha",
    "maxResults": 200
}
```

#### Browse by Category with Full Details

Pull every hair, cosmetic, nail, and massage business in Brno with IČO, email, and full opening hours. Leave the keyword blank when you browse a category — a keyword and a category are alternatives, and the keyword wins if you set both:

```json
{
    "category": "zdravi-krasa",
    "location": "Brno",
    "includeDetails": true,
    "maxResults": 500
}
```

#### Paste Firmy.cz URLs Directly

Replicate exact firmy.cz filters by pasting search-result URLs:

```json
{
    "searchUrls": [
        "https://www.firmy.cz/?q=lek%C3%A1rna&x=17.250879&y=49.594540&rt=mesto",
        "https://www.firmy.cz/?q=autoservis&x=14.42076&y=50.087811&rt=mesto"
    ],
    "maxResults": 0
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchUrls` | string\[] | `[]` | Paste one or more firmy.cz search-result URLs. When provided, these override the guided fields below. |
| `searchQuery` | string | `"restaurace"` | Free-text Czech keyword (e.g. "zubař", "autoservis", "kavárna"). |
| `location` | string | `""` | Czech city or area to scope the search (e.g. "Praha", "Brno", "Plzeň"). Leave blank for nationwide. |
| `category` | select | `All Categories` | Browse one of firmy.cz's 12 top-level categories, or the Beauty & Body Care section — see list below. Use it *instead of* a keyword: if you set both, the keyword is used and the run tells you the category was skipped. |

#### Category Options

| Value | Meaning |
|-------|---------|
| `all` | All Categories |
| `restauracni-sluzby` | Restaurants & Food |
| `auto-moto` | Auto & Motoring |
| `elektro-mobily-pocitace` | Electronics, Phones & Computers |
| `obchody` | Shops & Retail |
| `sluzby-a-remesla` | Services & Trades |
| `dum-byt-zahrada` | Home, Apartment & Garden |
| `zdravotnictvi` | First Aid & Healthcare |
| `zdravi-krasa` | Beauty & Body Care (section inside Services & Trades) |
| `banky-finance` | Banks & Finance |
| `cestovni-sluzby` | Travel Services |
| `instituce-urady` | Institutions & Government |
| `vse-pro-firmy` | Business Services |
| `velkoobchod-vyroba` | Wholesale & Manufacturing |

#### Output Detail & Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includeDetails` | boolean | `false` | Visit each business's profile page to capture IČO, email, full opening week, social links, amenities, and full photo gallery. Slower but much richer. |
| `maxResults` | integer | `200` | Exact cap on rows delivered and billed. Set to `0` for unlimited (a 50,000 internal safety cap still applies). |

### Output

Here's a representative business record with detail enrichment enabled:

```json
{
    "premiseId": "13099473",
    "name": "Lékárna U Černého orla",
    "categories": ["Lékárny", "Zdraví a krása"],
    "description": "Lékárna v centru Olomouce",
    "businessDescription": "A traditional pharmacy in the centre of Olomouc offering a wide range of medicines and medical supplies.",
    "address": "Horní náměstí 17, 779 00 Olomouc",
    "streetAddress": "Horní náměstí 17",
    "locality": "Olomouc",
    "postalCode": "779 00",
    "latitude": 49.5938,
    "longitude": 17.2509,
    "telephone": "+420 585 224 111",
    "email": "info@lekarna-olomouc.cz",
    "webUrl": "https://www.lekarna-olomouc.cz/",
    "socialLinks": ["https://www.facebook.com/lekarnaolomouc"],
    "ratingValue": 4.6,
    "ratingCount": 87,
    "reviewCount": 23,
    "ratingText": "Výborné",
    "openingInfo": "Otevřeno · zavírá v 18:00",
    "openingHours": {
        "monday": "08:00-18:00",
        "tuesday": "08:00-18:00",
        "wednesday": "08:00-18:00",
        "thursday": "08:00-18:00",
        "friday": "08:00-18:00",
        "saturday": "09:00-13:00"
    },
    "logoUrl": "https://d48-a.sdn.cz/d_48/c_img_QM_T/logo-lekarna.jpg",
    "photoUrl": "https://d48-a.sdn.cz/d_48/c_img_QO_R/main.jpg",
    "photos": ["https://d48-a.sdn.cz/d_48/p1.jpg", "https://d48-a.sdn.cz/d_48/p2.jpg"],
    "ico": "26789012",
    "dataBoxId": "x9y8z7w",
    "amenities": ["Barrier-free", "Card payment", "Parking"],
    "tags": ["verified", "top-firma-2025"],
    "priceRange": null,
    "bookingUrl": "https://lekarna-u-cerneho-orla.cz/rezervace/",
    "detailPageUrl": "https://www.firmy.cz/detail/13099473-lekarna-u-cerneho-orla-olomouc.html",
    "searchUrl": "https://www.firmy.cz/?q=lek%C3%A1rna&x=17.2509&y=49.5938&rt=mesto",
    "scrapedAt": "2026-05-04T11:42:18Z"
}
```

Closed days are simply absent from the `openingHours` object — `Sunday` is omitted when the business is closed that day.

#### Identity & Categories

| Field | Type | Description |
|-------|------|-------------|
| `premiseId` | string | Stable firmy.cz business identifier — safe for deduplication across runs |
| `name` | string | Business name (Czech UTF-8) |
| `categories` | string\[] | Czech category labels assigned by Seznam |
| `description` | string | Short tagline from the search result card (always available when published) |
| `businessDescription` | string | Full business description from the detail page, in English (detail mode only) |
| `detailPageUrl` | string | Direct firmy.cz profile URL |

#### Address & Location

| Field | Type | Description |
|-------|------|-------------|
| `address` | string | Full formatted address |
| `streetAddress` | string | Street and house number |
| `locality` | string | City or town |
| `postalCode` | string | Czech PSČ (postal code) |
| `latitude` | number | Latitude in decimal degrees |
| `longitude` | number | Longitude in decimal degrees |

#### Contact & Booking

| Field | Type | Description |
|-------|------|-------------|
| `telephone` | string | Phone number in international format |
| `email` | string | Business email (detail mode only) |
| `webUrl` | string | Business website URL |
| `socialLinks` | string\[] | Facebook, Instagram, LinkedIn, YouTube links (detail mode only) |
| `bookingUrl` | string | Direct reservation link when the business publishes one — table bookings, hotel booking engines, appointment slots |

#### Rating & Reviews

| Field | Type | Description |
|-------|------|-------------|
| `ratingValue` | number | Star rating on a 0–5 scale |
| `ratingCount` | number | Total number of ratings |
| `reviewCount` | number | Number of written reviews |
| `ratingText` | string | Czech rating label (e.g. "Výborné", "Dobré") |

#### Hours & Media

| Field | Type | Description |
|-------|------|-------------|
| `openingInfo` | string | One-line open/closed status (e.g. "Otevřeno · zavírá v 18:00") |
| `openingHours` | object | Full weekly schedule keyed by lowercase English day (`monday`–`sunday`) with values like `"08:00-18:00"`. Closed days are omitted (detail mode only). |
| `logoUrl` | string | Business logo image URL |
| `photoUrl` | string | Primary photo URL from the listing card |
| `photos` | string\[] | Full photo gallery (detail mode only) |

#### Czech Identifiers & Tags

| Field | Type | Description |
|-------|------|-------------|
| `ico` | string | IČO — Czech business ID (detail mode only) |
| `dataBoxId` | string | Datová schránka identifier (detail mode only) |
| `amenities` | string\[] | Amenity tags in English (parking, card payment, accessibility, etc., detail mode only) |
| `tags` | string\[] | Seznam listing badges: `verified` (business confirmed by Seznam) and `top-firma-<year>` (category award winner) |
| `priceRange` | string | Price range label when published |

#### Traceability

| Field | Type | Description |
|-------|------|-------------|
| `searchUrl` | string | The firmy.cz URL the row originated from |
| `scrapedAt` | string | ISO 8601 timestamp of extraction |

### Tips for Best Results

- **Use Czech keywords** — firmy.cz indexes Czech-language terms (`lékárna`, `zubař`, `autoservis`). English equivalents return far fewer matches.
- **Pre-resolve the city in the `location` field** — typing "Praha" auto-maps to Seznam's `mesto` scope; districts like "Brno-venkov" map to `okres`, and regions like "Jihomoravský kraj" map to `kraj`. Pasting a manual URL with `&rt=mesto` / `&rt=okres` / `&rt=kraj` lets you replicate firmy.cz's own filters exactly.
- **Turn on detail enrichment for B2B work** — IČO, Datová schránka, and email only appear in detail mode. Without them, rows lack the Czech identifiers needed for invoicing and KYC.
- **Use `maxResults: 0` for full-market sweeps** — a single category-and-city query like Olomouc pharmacies returns over 1,300 rows. The 50,000 internal safety cap protects you from infinite pagination.
- **Pick the category, not a word that sounds like it** — browsing the Electronics category returns electronics retailers; searching the keyword `elektro` also returns electricians, electrical installers, and anything else with that stem in its name. Use the category dropdown whenever a whole trade is what you want, and the keyword box when you want one specific thing.
- **Mix URLs and guided fields** — paste two or three firmy.cz URLs alongside a keyword search to combine pre-built filters with broad sweeps in a single run.
- **Start at 50 rows** to verify the data shape, then scale to thousands. Whatever number you set is exactly what lands in your dataset, so a small test run costs exactly what you expect.
- **Reviews are intentionally summarized** — firmy.cz gates full review text behind a Seznam.cz login, so this actor returns rating values and counts but does not scrape full review bodies.

### Pricing

**$4.00 per 1,000 results** — undercuts the comparable directory-scraper market by roughly 20%. No compute charges — you only pay per result returned.

| Results | Estimated Cost |
|---------|----------------|
| 100 | $0.40 |
| 1,000 | $4.00 |
| 10,000 | $40.00 |
| 100,000 | $400.00 |

A "result" is any business row in the output dataset. Platform fees (storage, bandwidth) are additional and depend on your Apify plan.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate Czech market research, B2B lead generation, and CRM enrichment using publicly listed business data. Users are responsible for complying with Czech and EU law (including GDPR), Seznam.cz's Terms of Service, and any applicable local regulations. Do not use extracted data for spam, harassment, or any unlawful purpose. When processing personal contact details, follow GDPR rules on lawful basis, transparency, and data subject rights.

# Actor input Schema

## `searchUrls` (type: `array`):

Paste one or more Firmy.cz search-result URLs (e.g. https://www.firmy.cz/?q=restaurace\&x=14.42076\&y=50.087811\&rt=mesto). When provided, these override the guided search fields below.

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

Free-text keyword to search (e.g. "restaurace", "zubař", "autoservis"). Searches all of Czech Republic by default unless a city is given below. Leave this empty if you want to browse a category below. Ignored when URLs are provided above.

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

Czech city or area to scope the search to (e.g. "Praha", "Brno", "Plzeň"). Leave empty to search nationwide. Ignored when URLs are provided above.

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

Browse a real Firmy.cz category instead of typing a keyword — you get everything Firmy.cz files under that category, not everything that happens to match a word. Covers all 12 of the site's top-level categories, plus Beauty & Body Care (a section inside Services & Trades, since Firmy.cz has no top-level beauty category). Leave the search keyword above EMPTY when you pick a category — the two are alternatives, not filters that stack. If both are set the keyword wins, the category is skipped, and the run log and status message say so. Also ignored when URLs are provided.

## `includeDetails` (type: `boolean`):

Visit each business's detail page to enrich the row with IČO, Datová schránka, business email, the full 7-day opening-hours table, social links, amenities, full description, and additional photos. Best-effort: if firmy.cz's consent gate refuses on a given run, the actor still returns full listing-tier data (name, address, phone, rating, geo, primary photo) and you'll see a one-line note that the detail-tier fields stayed empty for that run. Slower (one extra request per business).

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

Maximum number of results to fetch across all sources. Default 200 — increase for bigger runs, or set to 0 for unlimited (capped at 50,000 per run as a safety limit). You are never charged for more than this number: if a page carries extra listings past your limit, the surplus is dropped before it reaches your dataset.

## Actor input object example

```json
{
  "searchUrls": [],
  "searchQuery": "restaurace",
  "category": "all",
  "includeDetails": false,
  "maxResults": 200
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped businesses with the most useful columns at a glance.

# 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 = {
    "searchUrls": [],
    "searchQuery": "restaurace",
    "location": "",
    "category": "all",
    "includeDetails": false,
    "maxResults": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/firmy-search-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 = {
    "searchUrls": [],
    "searchQuery": "restaurace",
    "location": "",
    "category": "all",
    "includeDetails": False,
    "maxResults": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/firmy-search-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 '{
  "searchUrls": [],
  "searchQuery": "restaurace",
  "location": "",
  "category": "all",
  "includeDetails": false,
  "maxResults": 200
}' |
apify call solidcode/firmy-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/firmy-search-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/gWXSFMM0ZdZtd7098/builds/dDZNA3ZEtUybLycgW/openapi.json
