Jobs.cz - Czech Jobs, Salary, Benefits & GPS avatar

Jobs.cz - Czech Jobs, Salary, Benefits & GPS

Pricing

from $1.20 / 1,000 job results

Go to Apify Store
Jobs.cz - Czech Jobs, Salary, Benefits & GPS

Jobs.cz - Czech Jobs, Salary, Benefits & GPS

Scrape Czech job listings from Jobs.cz. Search builder (keyword, location, field, salary, employment type) or paste any Jobs.cz URL. Title, company, salary range with currency and period, benefits, GPS coordinates, required education and languages, employer contact info, remote/hybrid flag,.

Pricing

from $1.20 / 1,000 job results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Jobs.cz Scraper: Czech Job Listings with Salary, GPS & Employer Contact

Jobs.cz Scraper turns Jobs.cz, the largest job board in the Czech Republic, into structured hiring data. Build a search from Czech-language keywords, location, field, salary range and employment type, or paste any Jobs.cz link, and get one row per job with title, company, location, salary, benefits, GPS coordinates, required education and languages, employer contact info and the full description. Run it once, resume a large crawl, or schedule it to monitor a search and get only what changed, then export the results to JSON, CSV or Excel, read them through the API, or pipe them straight into the apps you already use.

Why This Scraper?

  • Search builder and URL mode. Build a search from a Czech-language keyword, location, field, salary range and employment type, or paste any Jobs.cz listing, search or direct position URL, mixed freely in one run.
  • Rich structured output. Salary range with currency and period, GPS coordinates, benefits, required education and languages, employment and contract type, suitability flags, employer phone, email and contact, remote or hybrid flag, posting date, and the full description in HTML and plain text, on a pasted single position link or with Fetch full job details on.
  • Czech-language aware. Field labels and descriptions are extracted and normalized, and salary text such as "150 000 - 185 000 Kč" is parsed into structured salary.min / salary.max.
  • Incremental monitoring, with a real limit. Schedule a recurring run against a search short enough to be read in full each time, and get only what changed. A search spanning more than a handful of pages is not currently guaranteed to be revisited in full on a scheduled run; see "Resume and recurring updates" below.
  • Honest about blocked runs. A run that cannot read a single page fails loudly with a clear message instead of finishing green with an empty dataset, and nothing is ever marked as gone while a page could not be read.

Use Cases

  • Recruiters and staffing agencies: track competing postings across sectors, regions and salary bands to benchmark your own openings.
  • Compensation and workforce researchers: build salary datasets by role, region and employment type straight from live listings.
  • Job aggregators and alert bots: mirror a whole professional field or a narrow keyword search and get notified only when something changes.
  • Talent sourcing tools: pull employer phone, email and contact name straight from a job posting to reach out directly.
  • Market and content teams: track new-posting volume and remote/hybrid trends per field or region over time.

Data You Get

Sample shape: values are illustrative placeholders, not from a live posting.

FieldExample
jobId"3300000001"
jobUrl"https://www.jobs.cz/rpd/3300000001/"
title"Senior Python Engineer, Cloud Platform"
companyName"Vzorová firma s.r.o."
location"Praha 4, Hlavní město Praha"
coordinates{ "latitude": 50.041, "longitude": 14.437 } (needs Fetch full job details)
salary{ "currency": "CZK", "min": 90000, "max": 120000, "unit": "měsíc" } (needs Fetch full job details)
salaryRaw"90 000 - 120 000 Kč / měsíc"
employmentTypes["Práce na plný úvazek"]
contractType / contractDuration"Pracovní smlouva" / "Na dobu neurčitou"
requiredEducation"Vysokoškolské / univerzitní" (needs Fetch full job details)
requiredLanguages["Angličtina, úroveň Pokročilá"] (needs Fetch full job details)
benefits["Stravenky", "Možnost občasné práce z domova"] (needs Fetch full job details)
remote / arrangementtrue / "remote" (derived from the benefits list)
postedDate"2026-06-01T09:00:00+02:00"
descriptionText"Hledáme zkušeného vývojáře, který posílí náš tým..." (needs Fetch full job details)
employerPhone / employerEmail"+420 200 300 400" / "kariera@example.com" (employer-site jobs only)
contactName / contactCompanyName"Personální oddělení" / "Vzorová firma s.r.o." (employer-site jobs only)
applyUrl / applyType"https://www.jobs.cz/jof/3300000001/" / "internal" (job-page jobs only)
detailSource"employer-site" (also "job-page", or null when Fetch full job details is off)
scrapedAt"2026-06-12T08:00:00.000Z"

In incremental mode, every row also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt. Jobs read from an employer's own careers micro-site additionally carry the suitability flags suitableForGraduate, suitableForDisabled, suitableForPensioner and suitableForMaternityLeave, plus companyAddress and employerProfileUrl; jobs hosted on Jobs.cz itself instead carry categories.

How to Use

  1. Pick a mode: search (build a search from keyword, location, field, salary and employment type) or url (paste Jobs.cz links).
  2. Fill in the fields for that mode. In search mode, leave everything blank to list every current opening.
  3. Set Max items (and, in url mode, Max pages) to control run size and cost, and turn on Fetch full job details if you need the full description, benefits, GPS and employer contact.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Search by keyword and location:

{
"mode": "search",
"keyword": "python",
"location": "Praha",
"maxItems": 20
}

Search one professional field, narrowed by location and employment type:

{
"mode": "search",
"field": "IS/IT",
"location": "Brno",
"employmentType": "full",
"maxItems": 15
}

Paste a listing URL and fetch full details:

{
"mode": "url",
"urls": ["https://www.jobs.cz/prace/praha/"],
"maxItems": 10,
"fetchDetails": true
}

Monitor a search on a schedule:

{
"mode": "search",
"keyword": "python",
"location": "Praha",
"incrementalMode": true,
"emitExpired": true,
"maxItems": 20
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/jobs-cz-scraper").call(run_input={"mode": "search", "keyword": "python", "location": "Praha"})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], job["companyName"], job.get("salaryRaw"))

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/jobs-cz-scraper').call({ mode: 'search', keyword: 'python', location: 'Praha' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Max items, Max pages and detail enrichment

maxItems is the run's overall cap (default 20; each of your searches or URLs gets a share of it). maxPages limits how many result pages are walked per search (about 20 to 30 jobs per page) and is unlimited by default, so maxItems alone decides where a run stops. Turning on Fetch full job details (fetchDetails) adds one request per job and is billed as a separate detail-enrichment charge on top of the base per-job price; leave it off to get only the search-result fields (title, company, location, salary text, employment type). Pasting a single position link (/rpd/{id}/) always fetches and bills its full detail regardless of this toggle, since the job's own page has to be read to return it at all.

Resume and recurring updates

  • A safety guard stops paging a search after three pages in a row that added no new job to the dataset, whether or not Resume or Incremental mode is involved. On a plain, non-recurring run this simply means you never crawl deep past a run of duplicates, which is harmless. On a recurring or resumed run it is a real limitation: since Incremental mode's own repeat visits deliberately produce runs of unchanged (held-back) pages, a stable search longer than a few pages can trip this guard on ordinary scheduled runs, not just on Resume, and stop before reaching pages further down that hold new or updated jobs. Keep your search narrow enough that its full result set fits within a handful of pages if you rely on Incremental mode or Resume for it; a broad, multi-page search is not currently guaranteed to be fully revisited by either feature.
  • Resume (resumeFromRunId) continues one interrupted crawl: paste its run or dataset ID and every job it already returned is skipped rather than re-fetched or re-billed. The crawl restarts from the first search page and walks forward again, so it hits the same three-page guard described above; if your earlier run already collected more than about three pages, a plain Resume on the same search will read pages 1 to 3, find them all already collected, and stop there rather than reaching new jobs deeper in. Paste the search as a URL-mode link with a page number that picks up where the earlier run stopped instead, if you need to keep extending a large crawl.
  • Incremental mode (incrementalMode) is for recurring monitoring of the same search: turn it on and schedule the run, and each run's state (what it saw last time) is remembered between runs, keyed on the search setup, or on stateKey if you set one. For a search short enough to be read in full every run, later runs return only NEW and UPDATED jobs (plus UNCHANGED ones if you turn on emitUnchanged). For a longer search, the same three-page guard above can end the walk early on a run where most pages are unchanged, which means some new or updated jobs deeper in the search can be silently missed that run, without the run reporting any error.
  • EXPIRED is only ever produced after a run that read every search page it asked for: never when maxItems/maxPages capped the run, never when resumeFromRunId was used, never when a page could not be read, and never when the three-page guard above ended the walk early. In practice this means EXPIRED (and, later, REAPPEARED) essentially never fires for a search wider than a handful of pages, since a stable search of that size tends to trip the guard on its own unchanged pages before reaching the end. Turning on emitExpired is what makes a job trackable as REAPPEARED later: only a job that a previous complete scan has already marked EXPIRED can come back as REAPPEARED, so with emitExpired left off, or with a search too wide to ever complete a scan, REAPPEARED never happens either.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each job, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where job pages should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (build a search) or url (paste Jobs.cz links).
keywordstring(none; prefill python)Free-text search, e.g. python, programátor, účetní. Leave blank to list everything (search mode).
locationstring(none; prefill Praha)Free-text location, e.g. Praha, Brno, Plzeň, resolved to a Jobs.cz locality automatically (search mode).
fieldstring(none)Professional field (obor) as Jobs.cz names it, e.g. IS/IT, Doprava. Widens the results rather than narrowing them (search mode).
minSalaryinteger0Minimum gross monthly salary in CZK; 0 = no salary filter (search mode).
employmentTypestring"" (all types)full, part, employment_contract, identification_number, agreement or internships (search mode).
educationstring"" (any)primary, high or uni (search mode).
arrangementstring"" (any)partial-work-from-home, work-mostly-from-home or flexible-hours; this is also where the remote/hybrid flag comes from (search mode).
urlsarray(none; prefill one sample URL)Jobs.cz listing, search or direct /rpd/{id}/ URLs to crawl (url mode).
maxItemsinteger20Stop after this many jobs across all searches/URLs.
maxPagesinteger0 (unlimited)Result pages to walk per search; 0 defers entirely to Max items.
fetchDetailsbooleanfalseOpen each job's detail page. Costs an extra detail-enrichment charge per delivered, actually-read row.
resumeFromRunIdstring(none)Continue one interrupted run without re-returning or re-billing jobs it already collected.
incrementalModebooleanfalseRecurring monitoring: return only NEW, UPDATED (and, once Emit expired jobs is also on, REAPPEARED/EXPIRED) jobs on later runs.
stateKeystring(none)Name or share the incremental-mode state; otherwise derived automatically from the search setup.
emitUnchangedbooleanfalseAlso return (and bill) jobs that have not changed since the last run (incremental mode).
emitExpiredbooleanfalseAlso return (and bill) jobs no longer found after a complete scan (incremental mode); also what makes a later REAPPEARED possible.
proxyobject{ "useApifyProxy": true }Connection settings.
mcpConnectorsarray(none)Optional: send a summary of each job to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which job pages are created.
maxNotifyListingsinteger50Cap on jobs exported to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live posting.

{
"jobId": "3300000001",
"jobUrl": "https://www.jobs.cz/rpd/3300000001/",
"title": "Senior Python Engineer, Cloud Platform",
"companyName": "Vzorová firma s.r.o.",
"companyLogo": "https://img.jobs.cz/logo/3300000001.png",
"location": "Praha 4, Hlavní město Praha",
"addressLocality": "Praha",
"addressRegion": "Hlavní město Praha",
"postcode": "14000",
"country": "Česká republika",
"coordinates": { "latitude": 50.041, "longitude": 14.437 },
"salary": { "currency": "CZK", "min": 90000, "max": 120000, "unit": "měsíc", "raw": "90 000 - 120 000 Kč / měsíc" },
"salaryRaw": "90 000 - 120 000 Kč / měsíc",
"employmentTypes": ["Práce na plný úvazek"],
"contractType": "Pracovní smlouva",
"contractDuration": "Na dobu neurčitou",
"hoursPerWeek": 40,
"requiredEducation": "Vysokoškolské / univerzitní",
"requiredLanguages": ["Angličtina, úroveň Pokročilá"],
"benefits": ["Stravenky", "Možnost občasné práce z domova", "Příspěvek na vzdělávání"],
"arrangement": "remote",
"remote": true,
"suitableForGraduate": false,
"suitableForDisabled": false,
"suitableForPensioner": false,
"suitableForMaternityLeave": false,
"postedDate": "2026-06-01T09:00:00+02:00",
"descriptionText": "Hledáme zkušeného vývojáře, který posílí náš tým...",
"contactCompanyName": "Vzorová firma s.r.o.",
"contactName": "Personální oddělení",
"employerPhone": "+420 200 300 400",
"employerEmail": "kariera@example.com",
"companyAddress": "Vzorová 12, Praha 4, 140 00, Česká republika",
"employerProfileUrl": "https://zetacompass.jobs.cz",
"detailSource": "employer-site",
"status": "Přidáno",
"scrapedAt": "2026-06-12T08:00:00.000Z"
}

Plan Requirement

This actor is pay per event: a small run-start fee, then a per-job charge for every job written to the dataset, plus an optional detail-enrichment charge only for jobs whose detail page was actually fetched and delivered. The Pricing tab on the actor page shows the current rates for each of these. The default connection works out of the box; for larger or more demanding runs, switching to the residential proxy group with country set to CZ can improve reliability.

FAQ

How much does it cost?

You pay a small run-start fee, then a per-job charge for every job written to the dataset. Turning on Fetch full job details adds a separate detail-enrichment charge, but only for jobs whose detail page was actually fetched and delivered: a job with no readable detail page, or one that incremental mode suppresses because nothing changed, is never charged that surcharge even though its detail page still had to be read to check. The Pricing tab on the actor page has the current rates.

This actor is an independent tool and is not affiliated with or endorsed by Jobs.cz, Alma Career, or LMC s.r.o. It reads only publicly available job-listing pages. You are responsible for how you use the data: follow Jobs.cz's terms of service and the laws that apply to you, and get legal advice if you plan commercial redistribution.

How do I get only new jobs on a schedule?

Turn on Incremental mode and schedule the run against the same search. The first run returns everything as NEW; later runs return only NEW and UPDATED jobs. REAPPEARED and EXPIRED are both off unless you also turn on Emit expired jobs, and even then EXPIRED only fires after a run that read every page of the search, so a job can only ever come back as REAPPEARED once a previous complete scan has already marked it EXPIRED.

Why did my run fail instead of returning an empty dataset?

If Jobs.cz refuses every request for a search page, or, for a single pasted job link, its detail page, the run stops with a clear error message instead of finishing with an empty dataset, and nothing is marked EXPIRED or removed from the incremental baseline. If some pages were read but not all, the run finishes with a partial-results warning: you get what was found, again with nothing marked EXPIRED. Re-run, ideally with the residential proxy group and country set to CZ.

Does it return salary and GPS for every job?

No. Many Czech listings do not publish a salary; when the site shows one, it is parsed into salary.min / salary.max with its currency and period. GPS coordinates come exact for jobs hosted on an employer's own careers micro-site, and are geocoded best-effort from the address for jobs hosted on Jobs.cz itself, only when Fetch full job details is on; not every job publishes an address to geocode.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable as they are scraped.

🔗 Want more Jobs data?

Pair this actor with these related scrapers from the same team:

💼 NHS UK
From $0.8/1k. Scrape nhs.uk Jobs listings into a flat dataset. Extract 50+ fields...
💼 Jobsite UK
From $1/1K. Collect UK job listings from Jobsite.co.uk at scale. Search by keyword...
💼 ZipRecruiter Scraper
From $1/1K. Scrape ZipRecruiter jobs with titles, companies, salaries, locations...
💼 Cwjobs UK
From $1/1k. Scrape tech and IT jobs from CWJobs.co.uk into clean, structured data. Search...
💼 We Work Remotely Scraper
Extract current remote job listings from weworkremotely.com. Use keyword search or WWR...
💼 SimplyHired
From $1/1K. Pull active SimplyHired jobs across the US, UK, Canada, Australia, Ireland...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.