# Jobs.cz Jobs Scraper (`automation-lab/jobs-cz-scraper`) Actor

Search Jobs.cz and extract structured Czech vacancy data for recruiting, labor-market analysis, exports, and recurring job monitoring.

- **URL**: https://apify.com/automation-lab/jobs-cz-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 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

## Jobs.cz Jobs Scraper

Extract public **jobs** and vacancy details from Jobs.cz into structured JSON, CSV, Excel, or any Apify integration.

Jobs.cz Jobs Scraper searches Czech vacancies, follows each result to its detail source, and returns a stable job ID, title, employer, workplace, disclosed salary, employment terms, work arrangement, requirements, description, posting metadata, and canonical URL.

Use it for one-time labor-market research or schedule the same input to monitor new and changed Czech vacancies.

### What does Jobs.cz Jobs Scraper do?

The Actor supports two discovery routes:

1. search Jobs.cz with one or more role, skill, or employer queries;
2. process real Jobs.cz search pages or individual vacancy URLs.

It paginates search results, deduplicates vacancies by Jobs.cz job ID, opens detail pages, normalizes the fields, applies optional filters, and saves accepted records to the default dataset.

Jobs.cz serves some vacancies on its standard detail layout and others on employer-hosted Jobs.cz career sites. The Actor handles both public layouts: standard details come from server-rendered HTML, while hosted career details use the same public data endpoint as the employer page.

### Who is it for?

- **Recruitment teams** tracking hiring activity by role, employer, or Czech locality.
- **Labor-market analysts** comparing vacancy counts, requested skills, and disclosed salaries.
- **Job aggregators** collecting canonical source links and normalized vacancy descriptions.
- **Sales and staffing teams** identifying employers actively recruiting in a chosen specialty.
- **Data engineers** feeding current Jobs.cz jobs data into a warehouse, sheet, or dashboard.
- **Candidates and career researchers** comparing current roles without copying pages manually.

This Actor focuses only on public Jobs.cz vacancies. It does not log in, apply for jobs, bypass access controls, or collect candidate profiles.

### Why use this Actor?

- Search and direct URL inputs use one consistent output model.
- Search pagination stops at user-controlled item and page limits.
- Stable `jobId` and `canonicalUrl` fields support recurring comparisons.
- Full descriptions and list-form requirements are included when public.
- Salary remains `null` when an employer does not disclose it; values are never invented.
- Standard Jobs.cz and employer-hosted Jobs.cz details are normalized together.
- Filters are verified against normalized detail data rather than trusted only from a URL.
- Direct HTTP is the default, keeping memory and network cost low.
- Optional proxy configuration is available if direct access degrades.
- Accepted items are charged once, after validation and filtering.

### What jobs data can I extract?

| Field | Meaning |
| --- | --- |
| `jobId` | Stable Jobs.cz vacancy identifier |
| `title` | Vacancy title |
| `employer` | Public employer name |
| `location` | Workplace address, city, district, or region |
| `salary` | Employer-disclosed salary text, otherwise `null` |
| `employmentType` | Full-time, part-time, or other source wording |
| `contractType` | Employment contract, freelance relationship, or other source wording |
| `contractDuration` | Permanent, fixed-term, or other stated duration |
| `workArrangement` | Normalized `remote`, `hybrid`, or `onsite` value |
| `education` | Required education when stated |
| `languages` | Required languages and proficiency |
| `categories` | Jobs.cz professions or employer career-site categories |
| `requirements` | List items extracted from the vacancy description |
| `description` | Full normalized public vacancy description |
| `contactName` | Public contact name when displayed |
| `contactPhone` | Public contact phone when displayed |
| `applicationUrl` | Public Jobs.cz application route when available |
| `canonicalUrl` | Canonical public vacancy URL |
| `sourceStatus` | Result-card response or promotional badge |
| `postedAt` | Publication timestamp when the source exposes it |
| `searchQuery` | Query that discovered the vacancy, or `null` for a direct detail URL |
| `searchPage` | Search page that discovered the vacancy |
| `scrapedAt` | ISO timestamp for this extraction |

Nullable fields reflect what the employer and page layout actually disclose.

### How to scrape Jobs.cz vacancies

1. Open the Actor in Apify Console.
2. Enter one or more values in **Search queries**, such as `python developer`.
3. Optionally add a Czech location, employment type, or work arrangement filter.
4. Set **Maximum vacancies** and **Maximum pages per search**.
5. Run the Actor.
6. Open the **Vacancies** dataset view.
7. Download JSON, CSV, XML, Excel, or connect the dataset to another service.
8. To monitor changes, schedule the same task and compare records by `jobId`.

A low `maxItems` value is best for the first run. Increase it after confirming the search and filters return the intended market segment.

### Input parameters

#### `searchQueries`

An array of real Jobs.cz search terms. Role, technology, employer, and Czech-language terms are supported because they are passed to Jobs.cz search.

```json
{
  "searchQueries": ["python developer", "data engineer"],
  "maxItems": 50,
  "maxPages": 3
}
```

#### `startUrls`

An optional array of Jobs.cz `/prace/` search URLs or `/rpd/` vacancy URLs.

```json
{
  "startUrls": [
    { "url": "https://www.jobs.cz/prace/praha/?q=prodej" }
  ],
  "maxItems": 20
}
```

Only `jobs.cz` URLs are accepted. Login, employer administration, and unrelated paths fail input validation.

#### `location`

Case-insensitive locality text. The Actor includes it during query discovery and verifies that each normalized vacancy location contains it.

Examples: `Praha`, `Brno`, or `Jihomoravský kraj`.

#### `employmentTypes`

Optional source-language text matches, such as `Práce na plný úvazek`. A vacancy without matching employment data is not emitted when this filter is active.

#### `workArrangements`

Keep any combination of:

- `remote`;
- `hybrid` or occasional home working;
- `onsite`.

Classification uses public arrangement badges and detail wording. Read the description for edge cases because employer terminology varies.

#### `maxItems` and `maxPages`

`maxItems` limits accepted dataset rows across all inputs. `maxPages` limits each query or search URL. The Actor stops once enough accepted vacancies are saved.

#### `proxyConfiguration`

Direct access is the default. A user can supply Apify Proxy settings if Jobs.cz access degrades from their run environment. Czech residential routing is the recommended fallback, but it is never enabled or charged automatically.

### Example output

The following shape is based on a current local extraction; public contact details are omitted from the example:

```json
{
  "jobId": "2001304864",
  "title": "Senior Data Engineer / Architect",
  "employer": "Atlas Copco Services s.r.o.",
  "location": "Holandská, 1006, Brno, Štýřice",
  "salary": null,
  "employmentType": "Full-time work",
  "contractType": "employment contract",
  "contractDuration": "Permanent",
  "workArrangement": "hybrid",
  "education": "Education is not important",
  "languages": ["English (Advanced)"],
  "categories": ["Information technology"],
  "requirements": ["Expert SQL skills and strong hands-on data engineering experience."],
  "description": "We are looking for a Senior Data Engineer / Architect...",
  "contactName": null,
  "contactPhone": null,
  "applicationUrl": "https://www.jobs.cz/rpd/2001304864/",
  "canonicalUrl": "https://www.jobs.cz/rpd/2001304864/",
  "sourceStatus": "Příležitost dne",
  "postedAt": "2026-07-31T00:00:00+02:00",
  "searchQuery": "python",
  "searchPage": 1,
  "scrapedAt": "2026-08-01T08:00:00.000Z"
}
```

Descriptions and arrays can be longer than this shortened documentation sample.

### How much does it cost to extract Jobs.cz vacancies?

The Actor uses pay-per-event pricing:

- one **Start** event per run;
- one **Item processed** event per accepted vacancy.

The start fee is **$0.0015**. At the BRONZE rate of **$0.0006 per vacancy**, 10 vacancies cost about **$0.0075**, 100 cost about **$0.0615**, and 1,000 cost about **$0.6015**, before higher-volume tier discounts.

Filtered-out, duplicate, unavailable, and failed records do not receive an item charge. Apify platform compute and proxy usage may be included or shown separately according to your Apify plan and active pricing screen. The live pricing table in Console is authoritative.

### Monitoring new and changed vacancies

A useful recurring workflow is:

1. save a Task with stable search queries and filters;
2. schedule it daily or weekly in Apify Console;
3. export `jobId`, `title`, `employer`, `location`, `postedAt`, and `scrapedAt`;
4. compare the current dataset with the previous run;
5. treat unseen `jobId` values as new vacancies;
6. compare normalized fields for changes;
7. treat IDs missing from later runs as possibly closed, then confirm against the canonical URL.

Each run writes only to its own default dataset, so results from an older run are not mixed into the current run.

### Export Jobs.cz jobs to spreadsheets and pipelines

The default dataset works with Apify integrations and dataset APIs.

Common patterns include:

- append rows to Google Sheets;
- load JSON into BigQuery, Snowflake, or PostgreSQL;
- trigger Make, Zapier, or n8n after a scheduled run;
- feed vacancy text into an approved classification or skill-tagging workflow;
- build a dashboard grouped by employer, locality, arrangement, or category;
- send internal notifications only for newly observed job IDs.

Use `jobId` as the primary source key. Do not rely on result order, which can change as Jobs.cz ranks vacancies.

### Use the Jobs.cz scraper API

Replace `APIFY_TOKEN` with your Apify API token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~jobs-cz-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["python developer"],"maxItems":10,"maxPages":2}'
```

To wait for results in one request:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~jobs-cz-scraper/run-sync-get-dataset-items?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["data engineer"],"location":"Brno","maxItems":10}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/jobs-cz-scraper').call({
  searchQueries: ['python developer'],
  maxItems: 25,
  maxPages: 3,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map(({ jobId, title, employer }) => ({ jobId, title, employer })));
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/jobs-cz-scraper').call(run_input={
    'searchQueries': ['data engineer'],
    'location': 'Brno',
    'maxItems': 25,
    'maxPages': 3,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
for item in items:
    print(item['jobId'], item['title'], item.get('employer'))
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/jobs-cz-scraper"
```

#### Claude Desktop, Cursor, and VS Code setup

Claude Desktop, Cursor, and VS Code can use this MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/jobs-cz-scraper"
    }
  }
}
```

Example prompts:

- “Run the Jobs.cz scraper for Python developer jobs and summarize employers by Czech city.”
- “Collect up to 50 data vacancies in Brno and list hybrid roles with their canonical URLs.”
- “Extract this Jobs.cz search URL and return job ID, title, salary, and employment type.”

### Accuracy, limits, and failure behavior

- Jobs.cz content changes continuously; a run is a point-in-time observation.
- Salary, publication date, contact, education, language, and contract fields may be absent.
- Employer-hosted career sites can use different languages from the main Czech listing.
- Work-arrangement classification follows source wording and may not capture informal flexibility.
- Search ranking and visible counts can differ by time, locale, cookies, or source experiments.
- Vacancies can close between search discovery and detail extraction; those rows are skipped without an item charge.
- The Actor retries transient timeouts, HTTP 429, and server failures with bounded backoff.
- An unrecognized response shape fails or warns instead of silently reporting a fake empty dataset.
- `maxPages` is a safety limit, not a promise that every Jobs.cz result will be collected.

For high-volume monitoring, split unrelated searches into separate Tasks. This makes failures, costs, and dataset comparisons easier to interpret.

### Proxy guidance

Start without a proxy. If direct runs receive repeated access errors, configure Apify Proxy and choose Czech residential routing.

Keep one coherent proxy session for a request attempt rather than rotating every successful detail. The Actor changes the bounded identity only when retrying a transient failure.

Proxy transfer has a cost. Test a small `maxItems` value before a larger proxied run. The Actor does not silently fall back from direct access to paid residential traffic.

### Responsible use and legality

Jobs.cz exposes vacancies publicly, but public availability does not remove user obligations.

- Review Jobs.cz terms and applicable robots guidance.
- Collect only the fields needed for a legitimate purpose.
- Respect copyright, database rights, privacy law, and employment regulations.
- Do not use public contact data for spam or unlawful profiling.
- Keep personal contact fields secure and delete them when no longer needed.
- Do not misrepresent stale vacancies as currently open.
- Apply reasonable run frequency and volume.

You are responsible for deciding whether your use, retention, and redistribution are lawful.

### Troubleshooting

#### The dataset is empty

Check that at least one search query or supported Jobs.cz URL was supplied. Remove restrictive location, employment, or work-arrangement filters and run with `maxItems: 5`. Confirm the same search currently has public vacancies on Jobs.cz.

#### Some fields are null

This usually means the employer does not disclose that value. Null salary or posting date is expected and is preferable to an inferred value.

#### A search returns fewer records than `maxItems`

Increase `maxPages`, loosen filters, or use a broader query. Closed vacancies and duplicate IDs are skipped. `maxItems` is a ceiling, not a guaranteed count.

#### The run reports access or transient HTTP errors

Retry a small direct run once. If the problem persists, configure a Czech residential proxy. Do not repeatedly launch large runs against the same failed route.

#### A direct vacancy URL fails validation

Use a public `https://www.jobs.cz/rpd/...` detail URL or a `https://www.jobs.cz/prace/...` search URL. Login, company administration, and third-party career domains are outside the input contract.

### FAQ

#### Can it scrape a whole Jobs.cz search?

Yes, within your `maxItems` and `maxPages` limits. Search result availability and source changes still apply.

#### Can I scrape one vacancy?

Yes. Put its public Jobs.cz `/rpd/` URL in `startUrls` and set `maxItems` to `1`.

#### Does it extract salary?

Yes when Jobs.cz or the hosted career detail discloses salary. Otherwise `salary` is `null`.

#### Does it apply for jobs?

No. It extracts public vacancy data only.

#### Does it need a login?

No. Authenticated pages and candidate data are not supported.

#### Does it always need a proxy?

No. Direct access is the default. Proxy use is explicit and optional.

#### Can it monitor removed jobs?

Scheduled datasets can be compared by `jobId`. Absence is a signal, not definitive proof of closure, so verify the canonical page before taking action.

#### Can I search jobs in Germany?

This Actor is for Jobs.cz and Czech vacancies. The broad keyword research phrase “jobs in Germany” was not adopted because the Actor does not support German job boards.

### Related Automation Lab Actors

- [Workday Jobs Scraper](https://apify.com/automation-lab/workday-jobs-scraper) for public vacancies hosted on Workday.
- [LinkedIn Jobs Scraper](https://apify.com/automation-lab/linkedin-jobs-scraper) for LinkedIn job discovery workflows.
- [Jobicy Jobs Scraper](https://apify.com/automation-lab/jobicy-jobs-scraper) for remote-oriented Jobicy listings.

Choose this Actor when Jobs.cz is the required source and Czech vacancy identity, terms, and descriptions are the core dataset.

### Support

When reporting a reproducible problem, include:

- a sanitized input;
- the failed run URL;
- expected versus actual behavior;
- whether a proxy was configured;
- one affected public Jobs.cz URL, if safe to share.

Do not post Apify tokens, private candidate data, or credentials.

# Actor input Schema

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

Keywords to search on Jobs.cz, such as a role, skill, or employer. Each query is paginated independently.

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

Optional Jobs.cz /prace/ search pages or /rpd/ vacancy detail URLs. Filters below are also applied to URL results.

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

Optional Czech city, region, or locality text. It is included in keyword discovery and verified against each vacancy location.

## `employmentTypes` (type: `array`):

Optional Jobs.cz employment-type text to match, for example Práce na plný úvazek. Matching is case-insensitive.

## `workArrangements` (type: `array`):

Optional arrangements to keep. Jobs.cz listings that mention home working are classified as hybrid or remote; all others are onsite.

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

Maximum number of matching vacancy records saved across all inputs.

## `maxPages` (type: `integer`):

Safety limit for Jobs.cz result pages processed for each search query or search URL.

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

Optional Apify Proxy settings. Direct access is used when omitted. If access degrades, use a Czech residential proxy session.

## Actor input object example

```json
{
  "searchQueries": [
    "python developer"
  ],
  "startUrls": [],
  "maxItems": 10,
  "maxPages": 2
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing all extracted Jobs.cz vacancy records.

# 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 = {
    "searchQueries": [
        "python developer"
    ],
    "startUrls": [],
    "maxItems": 10,
    "maxPages": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/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 = {
    "searchQueries": ["python developer"],
    "startUrls": [],
    "maxItems": 10,
    "maxPages": 2,
}

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

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/NmCkwpAntfAkUXMMc/builds/goEmFRaoMpNNh33hu/openapi.json
