# Jobs-cz Jobs Scraper (`datawatcher/jobs-cz-scraper`) Actor

Scrapes job offers from jobs.cz: salaries, contract types, work mode, experience levels, locations and the full description. Same output schema as our other Polish job portal actors.

- **URL**: https://apify.com/datawatcher/jobs-cz-scraper.md
- **Developed by:** [DataWatcher](https://apify.com/datawatcher) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 job 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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

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

## How to integrate an Actor?

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

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

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

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

# README

## Jobs-cz Jobs Scraper

Scrape **jobs.cz** job offers as clean data, from the Apify Store or through the Apify API. Each row has a **title, company, city, contract type and salary**. Search by **keyword, city, category, contract, work type or experience**. Switch on one option to read each offer's own page for the **full description**.

### 🔎 What does Jobs-cz Jobs Scraper do?

- Reads job offers from jobs.cz and returns one row per offer.
- Searches by keywords, or reads a jobs.cz listing page or a single offer page that you give it.
- Filters by city, category, contract type, work type, experience level and "salary shown".
- Turns the pay text into numbers: minimum, maximum, currency and period.
- Can open each offer's page for the description, benefits, languages and extra details.

### ⭐ Why this one

> **1️⃣ One schema across job portals.**
> All our job actors share one output schema and one input schema. Build your pipeline once: our other job actors ([Nofluffjobs](https://apify.com/datawatcher/nofluffjobs-scraper), [Aplikuj](https://apify.com/datawatcher/aplikuj-scraper), [Bluelionjob](https://apify.com/datawatcher/bluelionjob-scraper), [Bulldogjob](https://apify.com/datawatcher/bulldogjob-scraper), [Hollylist](https://apify.com/datawatcher/hollylist-scraper), [Just Join IT](https://apify.com/datawatcher/justjoin-scraper), [Pracuj](https://apify.com/datawatcher/pracuj-scraper), [Reed](https://apify.com/datawatcher/reed-scraper), [RocketJobs.pl](https://apify.com/datawatcher/rocketjobs-scraper), [Skillshot](https://apify.com/datawatcher/skillshot-scraper), [theprotocol.it](https://apify.com/datawatcher/theprotocol-scraper)) take the same input and return the same fields, so adding a portal means changing the actor name, not your code.

- **Six ways to start.** Run it with no input, with keywords, with filters, with a listing URL, with one offer URL, or with a mix of URLs.
- **Pay as numbers.** Salary text becomes `min`, `max`, `currency` and `period`, so you can sort and compare it.
- **Cheap by default.** A listing row costs $0.40 per 1,000 results. The median result price of the ten most-used job scrapers in the Store is $1.75 per 1,000.
- **Details only when you ask.** The extra charge for reading an offer's page applies only to offers whose page was read.
- **Six filters.** City, category, contract type, work type, experience and "salary shown" narrow the rows.

### 🚀 How to scrape jobs.cz jobs

1. Open the actor on Apify and click **Try for free**.
2. Type keywords, a city or a jobs.cz URL, or leave the input empty to read the default search. Turn on **Extract full details** if you want the description.
3. Click **Start**.
4. Download the **jobs.cz jobs data** as JSON, CSV or Excel from the Output tab, or fetch it with the Apify API.

### Data

This actor returns only what the site shows publicly at run time. We don't store or keep that data and are not its controller — you decide how you use it.

This actor is not affiliated with or endorsed by jobs.cz. Salary and contract data appear only where the offer shows them.

### 🤖 Use with AI agents (MCP)

AI assistants (Claude, ChatGPT, Cursor…) can run this actor through Apify's MCP server. Connect the server in your assistant, then ask, for example:

```text
Use the Jobs-cz Jobs Scraper to find 20 job offers for "python" in Praha on jobs.cz and show me the title, company and salary of each.
```

### 🔌 Run it your way

- **Schedule it** with Apify schedules.
- **Call it from the Apify API** and its clients (Python, JavaScript).
- **Connect it** to Make, n8n, Zapier, webhooks or Google Sheets.
- **Ask an AI agent to run it**: see [Use with AI agents (MCP)](#-use-with-ai-agents-mcp).

### ⚙️ Input

Every field is optional. Pick one of the modes below, or combine them.

```json
{
  "searchQueries": ["python"],
  "locations": ["Praha"],
  "maxResults": 10,
  "extractFullDetails": false
}
```

| Field | Default | Notes |
| --- | --- | --- |
| `maxResults` | 50 | Maximum number of offers returned, in total. Set 0 to remove the cap. |
| `startUrls` | empty | A listing URL is read as that listing. An offer URL is read directly. The filters below still apply to these URLs. `searchQueries` is not applied to them. |
| `searchQueries` | empty | Keywords, one search per line: a technology or a job title. |
| `locations` | empty | City names. Accents and case do not matter. A city the portal does not know gives a warning and no search for it. |
| `categories` | empty | One or more of `backend`, `frontend`, `fullstack`, `mobile`, `devops`, `data`, `ai-ml`, `testing`, `security`, `it-admin`, `support`, `embedded`, `gamedev`, `erp`, `architecture`, `project-management`, `product`, `ux-ui`, `business-analysis`, `sales`, `marketing`, `hr`, `finance`, `customer-service`, `engineering`, `production`, `logistics`, `legal`, `administration`, `consulting`, `education`, `healthcare`, `construction`, `hospitality`. |
| `contractTypes` | empty | One or more of `employment`, `b2b`, `mandate`, `specific-task`, `internship`. |
| `workType` | empty | One or more of `remote`, `hybrid`, `onsite`, `mobile`. |
| `experience` | empty | One or more of `intern`, `junior`, `mid`, `senior`, `expert`, `lead`, `manager`, `executive`. |
| `withSalaryOnly` | off | Keep only offers that show a salary. |
| `extractFullDetails` | off | Read each offer's own page for the description, skills, benefits, languages and company details. An offer start URL is read either way. |
| `maxConcurrency` | 1 | Searches and detail pages processed in parallel (1 to 10). |
| `maxRequestsPerMinute` | 60 | Request rate for the whole run. |
| `proxyConfiguration` | off | Optional proxy settings, useful when many detail pages are requested. |
| `maxRequestRetries` | 2 | Retries after a failed request (0 to 10). |

When you filter by work type without `extractFullDetails`, rows that the listing alone cannot confirm are left out, and the run reports a warning. Turn on `extractFullDetails` to check them on each offer's page.

### 🧭 Input modes: what you give, what you get

Pick the mode that matches what you know. Each one runs with `extractFullDetails` off or on.

| Mode | You give | Rows | Offer pages read |
| --- | --- | --- | --- |
| 1. Default search | nothing | Offers from the default jobs.cz search | Only with `extractFullDetails` |
| 2. Keywords | `searchQueries` | Offers matching the keywords | Only with `extractFullDetails` |
| 3. Filtered search | `locations`, `categories`, `contractTypes`, `workType`, `experience` or `withSalaryOnly` | Offers matching the filters | With `extractFullDetails`, or when a filter needs the page |
| 4. Listing URL | a jobs.cz listing URL in `startUrls` | Offers from that listing | Only with `extractFullDetails` |
| 5. One offer URL | an offer URL in `startUrls` | That one offer, with full details | Yes, the offer page is read |
| 6. Mixed URLs | a listing URL and an offer URL in `startUrls` | Offers from the listing plus the offer | The offer URL is read directly, listing offers with `extractFullDetails` |

Copy one of the inputs below and change the values.

#### 🔎 1. Default search

```json
{
  "maxResults": 10
}
```

#### 🔤 2. Keywords

```json
{
  "searchQueries": ["specialista"],
  "maxResults": 10
}
```

#### 🎯 3. Filtered search

```json
{
  "locations": ["Praha"],
  "workType": ["hybrid"],
  "maxResults": 10,
  "extractFullDetails": true
}
```

#### 📄 4. Listing URL

```json
{
  "startUrls": [{ "url": "https://www.jobs.cz/prace/" }],
  "maxResults": 10
}
```

#### 📌 5. One offer URL

```json
{
  "startUrls": [{ "url": "https://www.jobs.cz/rpd/2001515826/" }]
}
```

#### 🔗 6. Mixed URLs

```json
{
  "startUrls": [
    { "url": "https://www.jobs.cz/prace/" },
    { "url": "https://www.jobs.cz/rpd/2001515826/" }
  ],
  "maxResults": 10
}
```

Filters apply to URL modes too: rows that do not match are dropped.

### 📦 Output: jobs.cz jobs data

Each row is one job offer. It holds the title, company, locations, categories, contract types, work time, salaries, benefits, languages, dates and the description. Salaries are listed as `min`, `max`, `currency`, `period` and `grossNet`. Fields the offer does not show stay empty.

```json
{
  "recordType": "job",
  "source": "jobs.cz",
  "id": "2001515826",
  "url": "https://www.jobs.cz/rpd/2001515826/",
  "title": "Staňte se srdcem naší farmy – HLEDÁME RECEPČNÍ!",
  "company": {
    "name": "RODINNÁ FARMA A-04 s.r.o."
  },
  "locations": [
    {
      "city": "Praha",
      "street": "Vinohradská 3217/167"
    }
  ],
  "contractTypes": [
    {
      "value": "employment",
      "original": "pracovní smlouva",
      "source": "portal"
    }
  ],
  "workTime": "full-time",
  "salaries": [
    {
      "contractType": "employment",
      "currency": "CZK",
      "min": 35000,
      "max": 38000,
      "period": "month",
      "isOriginal": true
    }
  ],
  "benefits": ["Multisport karta"],
  "description": {
    "text": "Rodinná farma je síť prodejen s farmářskými produkty a výběrovými uzeninami. ..."
  },
  "dates": {
    "scraped": "2026-11-13T14:00:17Z"
  }
}
```

Missing data is `null`, never a guess.

**Run status.** After each run, open the run's key-value store (Storage tab) to see how it went:

- **`RUN_HEALTH`**: `ok`, or `degraded` with the reason (no rows, a failed request, a warning, or a row that broke a data rule).
- **`RUN_SUMMARY`**: the run's numbers: rows, requests, retries, failed requests, warnings and billed events.

### 💰 Pricing (Pay-Per-Event)

| Event | Price | Trigger |
| --- | --- | --- |
| Job result (`job-scraped`) | $0.40 per 1,000 events | One job offer returned by the Actor. |
| Job details (`job-details-scraped`) | $1.50 per 1,000 events | Additional charge for a job offer whose detail page was read. |

There is no start fee. You pay for the offers returned, plus the extra event when an offer's page was read.

Free plan: each run returns up to 1,000 results.

### 🎯 Use cases

- **Hiring demand.** Count new offers by category or city over time.
- **Employer watch.** See which companies post the most offers.
- **Pay research.** Compare the minimum and maximum salary by role, city and contract type.
- **Job boards.** Fill a board with current Czech offers.

### 🩺 If a run fails

The run health (the `RUN_HEALTH` record, `RUN_SUMMARY` and the last line of the log) names the cause, for example `site down: list request answered 500 x3`. Find that start of the message in the table.

| Error in the log / run health | What it means | What you do |
|---|---|---|
| `site down: <request> answered 500, 502-504, 520-526` | The site is offline or has a fault. The actor waits longer between tries, then stops the run. | Try again later. |
| `blocked: <request> answered 401, 403, 1020` or a captcha page | The site refused the request or showed a captcha page. | The actor already retries once through the Apify proxy. If it still fails, turn on the Apify proxy in the input (use the RESIDENTIAL group if it is already on). |
| `rate limited: <request> answered 429` | The site asks for fewer requests. The actor waits and slows down by itself. | If it keeps happening, lower `maxRequestsPerMinute`. |
| `gone: <request> answered 404, 410` | The page or offer was removed. The actor skips it and it is not charged. | Nothing; this is normal. |
| `network error: <request> failed with timeout` (or connection error, DNS error) | A timeout or a broken connection. The actor retries with a pause. | Try again later. |
| `wrong answer: <request> returned HTML instead of JSON` (or an empty body) | The site answered with a page that is not data (HTML instead of JSON, an empty body). The site has probably changed. | Report it in the Issues tab; we fix it. |

### ❓ FAQ

#### How many jobs can I scrape per run?

Set `maxResults` to the number you want. The free plan returns up to 1,000 results per run.

#### How do I export jobs.cz jobs to Excel or CSV?

Run the actor, open the Output tab and pick Excel or CSV in the export options. JSON, XML and HTML are there too, and the Apify API returns the same data.

#### Can I scrape only offers that show a salary?

Yes. Turn on `withSalaryOnly`. Offers without a salary are dropped.

#### Can I combine it with other portals?

Yes. All our job actors share one output schema and one input schema, so rows from different portals fit one table. See the list below.

### 🔗 Other job scrapers (same schema)

- [Nofluffjobs Jobs Scraper](https://apify.com/datawatcher/nofluffjobs-scraper)
- [Aplikuj Job Scraper](https://apify.com/datawatcher/aplikuj-scraper)
- [Bluelionjob Jobs Scraper](https://apify.com/datawatcher/bluelionjob-scraper)
- [Bulldogjob Jobs Scraper](https://apify.com/datawatcher/bulldogjob-scraper)
- [Hollylist Jobs Scraper](https://apify.com/datawatcher/hollylist-scraper)
- [Just Join IT Jobs Scraper](https://apify.com/datawatcher/justjoin-scraper)
- [Pracuj Job Scraper](https://apify.com/datawatcher/pracuj-scraper)
- [Reed Jobs Scraper](https://apify.com/datawatcher/reed-scraper)
- [RocketJobs.pl Jobs Scraper](https://apify.com/datawatcher/rocketjobs-scraper)
- [Skillshot Jobs Scraper](https://apify.com/datawatcher/skillshot-scraper)
- [theprotocol.it Jobs Scraper](https://apify.com/datawatcher/theprotocol-scraper)

### 💬 Feedback and custom work

Need another portal, a field or a custom feed? Open an issue on the Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/datawatcher/jobs-cz-scraper/changelog.md

# Actor input Schema

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

Maximum number of offers returned, in total. 0 = no limit (the run timeout still applies). Free plan Apify users get at most 1000 offers per run, whatever is set here (paying users have no cap).

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

URLs from which the actor starts scraping, instead of a search: a listing/search URL is read as that listing, a specific offer URL is read directly. locations, categories, contractTypes, workType, experience and withSalaryOnly still apply: rows that do not match are dropped. searchQueries is not applied (a warning says so).

## `searchQueries` (type: `array`):

Keywords to search for, one search per line (a technology or a job title). Empty - every offer.

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

Only offers in these cities, written as normal city names; accents and case do not matter (Krakow = Kraków = KRAKÓW). A city the portal does not know gives a warning and no search for it, never an unfiltered search. Empty - anywhere.

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

Only offers in these categories (the output's `categories[].value` values). Empty - all.

## `contractTypes` (type: `array`):

Only offers that allow one of these contracts (the output's `contractTypes` values). Empty - all.

## `workType` (type: `array`):

Only offers with one of these work types (the output's `workType[].type` values). Empty - all.

## `experience` (type: `array`):

Only offers for these experience levels (the output's `experience.levels[].value` values). Empty - all.

## `withSalaryOnly` (type: `boolean`):

Only offers that show a salary (the output's `salaries` is not empty). Off - all offers.

## `extractFullDetails` (type: `boolean`):

Fetch each offer's own page (and its company once per run) and return the full data: the description, skills, benefits, languages, company details. Off - listing-level data only, cheaper and faster. An offer start URL is always read. A filter whose field the listing lacks still reads that offer's page to decide.

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

Maximum number of searches/details processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Maximum HTTP request rate, for the whole run.

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

Proxy settings, especially useful when many detail pages are requested.

## `maxRequestRetries` (type: `integer`):

Number of retries after a failed HTTP request.

## Actor input object example

```json
{
  "maxResults": 10,
  "searchQueries": [
    "python"
  ],
  "withSalaryOnly": false,
  "extractFullDetails": false,
  "maxConcurrency": 1,
  "maxRequestsPerMinute": 60,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 2
}
```

# Actor output Schema

## `results` (type: `string`):

One row per item; a search that failed completely adds one unbilled recordType "diagnostic" row.

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

Rows, requests and budget, retries, failures, early stop, warnings, billing events, data-rule problems.

## `runHealth` (type: `string`):

{status, reason}: ok, degraded, or failed (health-check mode only).

# 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 = {
    "maxResults": 10,
    "searchQueries": [
        "python"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datawatcher/jobs-cz-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 = {
    "maxResults": 10,
    "searchQueries": ["python"],
}

# Run the Actor and wait for it to finish
run = client.actor("datawatcher/jobs-cz-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 '{
  "maxResults": 10,
  "searchQueries": [
    "python"
  ]
}' |
apify call datawatcher/jobs-cz-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datawatcher/jobs-cz-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/5DVM1rshAytMUTyHW/builds/1bQarxVUuaZLLqQYx/openapi.json
