# Czech Jobs.cz Postings, Salary & Brigady Finder (`xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder`) Actor

Search Jobs.cz Czech job postings and part-time brigady gigs by keyword, city, or profession, with salary, employment type, education, and language filters.

- **URL**: https://apify.com/xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder.md
- **Developed by:** [Xyrelith Data](https://apify.com/xyrelith-data) (community)
- **Categories:** Jobs, Automation, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 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/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

## Czech Jobs.cz Postings, Salary & Brigady Finder

Scrape **Jobs.cz** — one of the largest Czech job boards — with one actor. Search by keyword, browse a city/region or profession, browse the separate part-time/temp gig board (**brigády**), or paste jobs.cz search and job URLs. Get salary (including structured ranges that the listing hides), full descriptions, benefits, education, languages, contract type, dates, remote-work type, categories, company logo, Atmoskop profile and public contact details.

The actor is HTTP-only, anonymous and cookieless. No login, API key, cookie or proxy setup is required.

### What this actor does

- **Five modes**
  - **Keyword search** — one or more free-text queries, optionally narrowed to a city or profession.
  - **Browse by region/city** — every open role in a city or region.
  - **Browse by category/profession** — every open role in a profession.
  - **Brigády** — jobs.cz's separate board for part-time, temporary, student and seasonal gigs.
  - **Scrape these URLs** — paste jobs.cz search pages, job detail pages, brigady pages, or employer-branded job pages.
- **Rich filters** — minimum monthly salary, posted-within window, employment type (full-time, part-time, internship, temporary), contract type, education, required languages, home-office arrangement, suitable-for group, employer type (direct/agency/NGO), minimum hourly rate (brigády), and search radius around a city.
- **Full detail enrichment** — description (plain text and HTML), structured salary with a hidden-salary flag, employment and contract details, education, languages, categories/professions, benefits, posted/updated/expiry dates, remote type, company logo, Atmoskop review count, and public contact name/phone when the listing shows them.
- **Large runs** — up to 10,000 records per run. Above 9,990 rows the actor splits a query by location or category and de-duplicates the results.
- **Omit-empty output** — fields the source does not expose are omitted, never filled with `null` or a placeholder.

### Output per job

| Field | What it contains |
|---|---|
| `jobId` | jobs.cz recruitment ID (or ad UUID for URL-only job pages) |
| `title`, `company`, `location`, `locations[]` | Job title, employer, and city/cities |
| `url` | Canonical jobs.cz job URL |
| `salaryText` | Visible salary label (e.g. `"30 000 – 32 000 Kč/měsíc"`) |
| `salaryMinCzk`, `salaryMaxCzk`, `salaryPeriod` | Visible salary bounds and period |
| `salary` | Structured salary: `minCzk`, `maxCzk`, `currency`, `period`, `visible`, `source` |
| `description`, `descriptionHtml` | Full job description, plain text and HTML |
| `detailSource` | `job-page`, `employer-site` or `listing` |
| `employmentTypes[]` | `full-time`, `part-time`, `internship`, `temporary` |
| `contractType`, `contractTypeText` | Normalised contract type and the original Czech label |
| `education`, `educationText` | Normalised education level and the original label |
| `languages[]` | Required languages as shown on the job page |
| `categories[]`, `professions[]` | Work areas and profession titles |
| `benefits[]` | Benefit list when published |
| `workLocationType` | `on-site`, `partially-remote` or `full-remote` |
| `suitableFor[]` | `graduates`, `students`, `retired`, `maternity`, `disabled`, `ukraine-refugees`, `entry-level`, `senior` |
| `postedDate`, `postedAt`, `updatedAt`, `validThrough` | ISO posting/update/expiry dates |
| `postedDateText`, `badge`, `tags[]` | Legacy listing labels (old-board rows only) |
| `isPromoted`, `adLanguage` | Promoted-slot flag and ad language (`cs`/`en`) |
| `companyLogoUrl` | Employer logo URL |
| `atmoskopRating`, `atmoskopUrl`, `atmoskopReviewCount` | Atmoskop employer-review data |
| `contactName`, `contactPhone` | Public contact shown on the listing (never email) |
| `searchQuery`, `searchLocation`, `searchUrl` | Traceability for the query that produced the row |
| `recordType`, `scrapedAt` | `"job"` and the scrape timestamp |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` / `byLocation` / `byCategory` / `brigady` / `byUrls` |
| `searchQueries` | string array | `[]` (Console prefill `["python"]`) | One or more keywords (mode=search). The legacy `searchQuery` key is still accepted. |
| `startUrls` | string array | – | jobs.cz search/job/brigady/employer URLs (mode=byUrls) |
| `location` | select | none | Curated city/region |
| `locationSlugCustom` | string | – | Custom jobs.cz city slug |
| `category` | select | none | Curated profession/category |
| `categorySlugCustom` | string | – | Custom jobs.cz profession slug |
| `salaryMinCzk` | integer | `0` | Minimum gross monthly salary (0–200,000 Kč) |
| `hourlyRateMin` | select | `any` | Minimum hourly rate for brigády |
| `radiusKm` | select | jobs.cz default | 0–50 km around a location (legacy pages) |
| `datePosted` | select | `any` | `any` / `24h` / `3d` / `7d` |
| `employmentTypes` | array | – | `full`, `part`, `internships`, `temporary` |
| `contractTypes` | array | – | `employment_contract`, `identification_number`, `agreement` |
| `education` | select | `any` | `any` / `primary` / `high` / `uni` |
| `languageSkills` | array | – | `cs`, `en`, `de`, `fr`, `ru`, `pl`, `it`, `es` |
| `homeOffice` | select | `any` | `partial-work-from-home`, `work-mostly-from-home`, `flexible-hours` |
| `suitableFor` | select | `any` | `graduates`, `students`, `retired`, `maternity`, `disabled`, `ukraine_refugees` |
| `employerType` | select | `any` | `direct`, `agency`, `ngo` |
| `includeDetails` | boolean | `true` | Open each job page for full details; off = faster list-only run |
| `maxItems` | integer | `30` (prefill 3) | Hard cap, 1–10,000 |

#### Example: keyword search in a city, with full details

```json
{
  "mode": "search",
  "searchQueries": ["python", "data engineer"],
  "location": "praha",
  "datePosted": "7d",
  "includeDetails": true,
  "maxItems": 100
}
```

#### Example: browse a profession with a salary floor

```json
{
  "mode": "byCategory",
  "category": "programator",
  "salaryMinCzk": 60000,
  "employmentTypes": ["full"],
  "maxItems": 250
}
```

#### Example: part-time gigs in Brno

```json
{
  "mode": "brigady",
  "location": "brno",
  "hourlyRateMin": "200",
  "datePosted": "7d",
  "maxItems": 50
}
```

#### Example: scrape specific job and search URLs

```json
{
  "mode": "byUrls",
  "startUrls": [
    "https://www.jobs.cz/rpd/2001506751/",
    "https://beta.jobs.cz/prace/praha/?keywords%5B%5D=ucetni",
    "https://csg.jobs.cz/detail-pozice?r=detail&id=1634646597"
  ],
  "maxItems": 100
}
```

#### Example: large list-only run

```json
{
  "mode": "byLocation",
  "location": "praha",
  "includeDetails": false,
  "maxItems": 10000
}
```

### Use cases

- **Salary benchmarking** — compare advertised Kč ranges by profession, city or seniority.
- **Labor-market research** — measure hiring volume by category and region over time.
- **Recruitment intelligence** — monitor competitors' open roles and posting velocity.
- **Job aggregators / HR tech** — feed structured Czech listings into a meta-search product.
- **Relocation and expat services** — surface English-friendly and remote-eligible roles.
- **Part-time work discovery** — collect brigády shifts by city and hourly rate.

### How it handles the site

- The main board is read from jobs.cz's current search application, which exposes the full result set as structured JSON. The older jobs.cz pages are used for brigády, radius filtering, flexible-hours filtering, and benefit/contact enrichment.
- If the older pages are blocked from the current network, the actor retries them through a rate-limited public mirror. Requests are paced so a long run does not turn into a burst.
- Page 333 (9,990 rows) is the current per-query ceiling. Larger requests are split by city or profession and de-duplicated.
- Each job page is opened only when `includeDetails` is on. After six consecutive detail failures the actor stops enrichment and returns list-level rows rather than failing the run.

### Limitations and notes

- **Hidden salary** — some employers publish a salary range in the job's structured data while the listing says "Plat neuveden" (salary not stated). The `salary` object includes it with `"visible": false`; the legacy flat salary fields stay visible-only.
- **External employer pages** — when a jobs.cz ad redirects to an employer's own career site, the actor returns the search-level fields and sets `detailSource: "employer-site"`. Many employer sites publish no job description in a machine-readable block, so `description` may be absent.
- **Benefits and contact** — these come from the public older job page. A listing that does not show them, or a page that is temporarily unavailable, simply omits those fields. Very large detailed runs are capped at 1,000 job-page enrichments, and benefits/contact at 200 older pages, so a 10,000-row run cannot time out; later rows keep every list-level field. Use `includeDetails: false` for maximum speed.
- **Beta job links** — a pasted `beta.jobs.cz/nabidka/<uuid>/` URL returns the beta detail fields (description, salary, dates, contract, education, languages) but not the older-page benefits/contact block, because that block is keyed by numeric jobs.cz ID. Use a numeric `www.jobs.cz/rpd/<id>/` URL when you need those two fields.
- **Radius and flexible hours** — these two filters are not supported by the current search application, so runs that use them switch to the older jobs.cz pages. If those pages are unreachable, the run reports it in the status message.
- **Search-plus-category** — the current jobs.cz search supports a keyword together with a city and a category. The older pages do not, so legacy-path runs ignore the keyword when a category is set.
- **Brigády filters** — the brigády board only supports keyword, city, date and hourly-rate filters. The remaining main-board filters are logged and ignored in that mode.
- **No GPS coordinates** — jobs.cz does not publish coordinates for these listings, so no fabricated location data is emitted.
- **Contract duration and change tracking** — jobs.cz publishes contract type but not a reliable contract duration, and there is no public incremental `changeType` field. The actor returns current listings rather than change deltas.

### FAQ

**What is the data source, and how fresh is it?**
The actor reads jobs.cz's public search and job pages at request time — there is no cache. It is an independent third-party scraper and is not affiliated with or endorsed by jobs.cz or LMC.

**Do I need a proxy, cookies or an account?**
No. The actor is anonymous, cookieless and proxy-free. If a page is blocked from the current network, it retries through a paced public mirror.

**Why do some rows have no salary?**
Many Czech employers do not disclose pay. `salaryText` and the flat `salaryMinCzk`/`salaryMaxCzk` fields are only filled when the listing shows a figure. The `salary` object can still contain a structured range with `"visible": false` when the site publishes it in machine-readable data but hides it on the page.

**Why is `description` missing on some rows?**
Descriptions are available for jobs hosted on jobs.cz. When an ad redirects to an employer's own career site, the actor sets `detailSource: "employer-site"` and returns the fields the search page exposes. It does not invent a description.

**What does `includeDetails` change?**
With `true` (default), the actor opens each job page for description, structured salary, contract, education, languages, benefits and public contact. With `false`, it returns list-level rows only — faster and cheaper for large volume runs or when you only need titles, companies, locations and salaries.

**Can I get more than 10,000 jobs?**
The actor caps a run at 10,000. jobs.cz itself serves at most 9,990 rows per query; the actor splits larger requests by city or profession to get past that ceiling. If the source has fewer matching jobs than requested, the status message reports the actual count.

**Why do brigády results ignore some filters?**
jobs.cz's brigády board is a separate product with a smaller filter set: keyword, city, date and minimum hourly rate. Main-board filters such as salary, contract type, education and employer type do not exist there, so the actor logs and ignores them in that mode.

**Can I paste a job URL instead of using a search mode?**
Yes. Use `mode: "byUrls"` and add search pages, job detail pages, brigády pages or employer-branded job pages to `startUrls`. Numeric job URLs return the listing plus benefit/contact enrichment; beta UUID links return the beta detail fields and omit the older-page benefit/contact block.

**Why does a keyword search sometimes include a loosely related job?**
jobs.cz's own relevance ranking can surface broad matches for single-word queries. Adding a city, category or a more specific phrase improves precision. Promoted search slots are skipped for keyword searches.

**Are contact details included?**
Only the public contact name and phone number that the listing itself displays. The actor does not collect or emit email addresses.

# Actor input Schema

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

What to fetch. Search by keyword, browse a city/region, browse a profession, browse the separate part-time brigady board, or scrape specific jobs.cz search and job URLs.

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

One or more free-text keywords, e.g. `python`, `účetní`, `řidič`. Each query is paginated and results are de-duplicated. The old `searchQuery` key is still accepted for saved tasks.

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

jobs.cz search pages, job detail pages, brigady pages, or employer-branded job URLs. Job URLs return full detail when the page publishes it; employer pages return title, company and URL.

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

Curated city/region. Required for mode=byLocation; narrows keyword and category searches; limits brigady to a 10-50 km radius. Pick `(none)` for no restriction.

## `locationSlugCustom` (type: `string`):

jobs.cz URL slug for a city not in the dropdown, e.g. `vsetin` or `havirov`. Overrides `location`. Use lowercase, no diacritics, hyphens for spaces. Not supported in mode=brigady.

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

Curated profession/category. Required for mode=byCategory; narrows a city browse. Pick `(none)` for no restriction. Not applied in mode=brigady.

## `categorySlugCustom` (type: `string`):

jobs.cz URL slug for a profession not in the dropdown, e.g. `architekt` or `ucitel`. Overrides `category`. Use the slug exactly as jobs.cz shows it. Not applied in mode=brigady.

## `salaryMinCzk` (type: `integer`):

Only return main-board jobs at or above this gross monthly salary in Czech crowns. jobs.cz filters on each ad's internal salary data, so non-disclosing ads are not excluded and can still match. Ignored in mode=brigady.

## `hourlyRateMin` (type: `string`):

Only return brigady gigs at or above this hourly rate. jobs.cz offers exactly these five fixed thresholds. Ignored in every other mode; use `salaryMinCzk` there.

## `radiusKm` (type: `string`):

Widen or narrow the distance match around a location. Has no effect without a location. The current jobs.cz search app ignores radius, so these runs use the legacy jobs.cz pages.

## `datePosted` (type: `string`):

Restrict results to jobs posted or updated within this window. Works in every mode, including brigady.

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

Full-time, part-time, internship/trainee or temporary work. Leave empty for any. Ignored in mode=brigady.

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

Type of legal working relationship. Leave empty for any. Ignored in mode=brigady.

## `education` (type: `string`):

Required education level. Ignored in mode=brigady.

## `languageSkills` (type: `array`):

Only return jobs requiring these languages. Leave empty for any. Ignored in mode=brigady.

## `homeOffice` (type: `string`):

Remote-work arrangement. `Flexible hours` is only available on legacy jobs.cz pages, so selecting it switches the run to those pages. Ignored in mode=brigady.

## `suitableFor` (type: `string`):

Only return jobs explicitly marked suitable for this group. Ignored in mode=brigady.

## `employerType` (type: `string`):

Whether the ad was posted by the direct employer or a recruitment agency/NGO. Ignored in mode=brigady.

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

Open each job page for description, structured salary, education, languages, contract, benefits and public contact details. Turn off for faster list-only runs.

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

Hard cap on emitted records (1-10,000). Above 9,990 the run is split by location or category to pass jobs.cz's per-query ceiling; duplicates are removed.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "python"
  ],
  "startUrls": [],
  "location": "",
  "category": "",
  "salaryMinCzk": 0,
  "hourlyRateMin": "any",
  "radiusKm": "",
  "datePosted": "any",
  "employmentTypes": [],
  "contractTypes": [],
  "education": "any",
  "languageSkills": [],
  "homeOffice": "any",
  "suitableFor": "any",
  "employerType": "any",
  "includeDetails": true,
  "maxItems": 3
}
```

# Actor output Schema

## `jobs` (type: `string`):

Dataset containing all scraped Jobs.cz job and brigady listings.

# 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",
    "searchQueries": [
        "python"
    ],
    "startUrls": [],
    "location": "",
    "category": "",
    "salaryMinCzk": 0,
    "hourlyRateMin": "any",
    "radiusKm": "",
    "datePosted": "any",
    "employmentTypes": [],
    "contractTypes": [],
    "education": "any",
    "languageSkills": [],
    "homeOffice": "any",
    "suitableFor": "any",
    "employerType": "any",
    "includeDetails": true,
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder").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",
    "searchQueries": ["python"],
    "startUrls": [],
    "location": "",
    "category": "",
    "salaryMinCzk": 0,
    "hourlyRateMin": "any",
    "radiusKm": "",
    "datePosted": "any",
    "employmentTypes": [],
    "contractTypes": [],
    "education": "any",
    "languageSkills": [],
    "homeOffice": "any",
    "suitableFor": "any",
    "employerType": "any",
    "includeDetails": True,
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder").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 '{
  "mode": "search",
  "searchQueries": [
    "python"
  ],
  "startUrls": [],
  "location": "",
  "category": "",
  "salaryMinCzk": 0,
  "hourlyRateMin": "any",
  "radiusKm": "",
  "datePosted": "any",
  "employmentTypes": [],
  "contractTypes": [],
  "education": "any",
  "languageSkills": [],
  "homeOffice": "any",
  "suitableFor": "any",
  "employerType": "any",
  "includeDetails": true,
  "maxItems": 3
}' |
apify call xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xyrelith-data/czech-jobs-cz-postings-salary-and-brigady-finder"
        }
    }
}
```

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/x1vYR6ixAeVfHRs61/builds/BrN1c4fDavcIJtqXr/openapi.json
