Career Site Jobs API: Job Postings from 19,000 Company Sites avatar

Career Site Jobs API: Job Postings from 19,000 Company Sites

Pricing

from $3.20 / 1,000 jobs

Go to Apify Store
Career Site Jobs API: Job Postings from 19,000 Company Sites

Career Site Jobs API: Job Postings from 19,000 Company Sites

Career site jobs API: search job listings on 19,000 company career sites (Workday, Greenhouse, Lever, Ashby, Oracle, iCIMS +8) by keyword, country, date and salary floor. Bench 10-09: 19 of 19 checks vs 11 of 19 for the most-used career site jobs API.

Pricing

from $3.20 / 1,000 jobs

Rating

0.0

(0)

Developer

hiver

hiver

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

10 days ago

Last modified

Categories

Share

A career site jobs API (a job postings and job listings API) that reads employers' own career sites: search open jobs by keyword, location and posting date across 19,029 company job boards on 14 job systems (Workday, Greenhouse, Lever, Ashby, Oracle, iCIMS, SmartRecruiters, Personio and more; about 0.8 to 1.0 million open jobs). Every match is re-read from the employer's own board, so closed jobs are dropped, and a pay range stated in the posting text lands in salaryMin / salaryMax.

One keyword search over company career sites: real output rows from a board test run on 2026-10-12

Watch the 1-minute walkthrough (MP4)

  • Coverage: 19,029 boards (about 15,000 companies) on Greenhouse (5,150), Ashby (3,270), Workday (1,609 sites of 1,075 companies), BambooHR (1,490), Personio (1,361), Breezy HR (1,224), Lever (906), Teamtailor (860), Rippling (831), iCIMS (779), SmartRecruiters (732), Oracle Recruiting Cloud (553), Recruitee (192) and Pinpoint (72). Workable (1,729 more boards) is opt-in. Details and gaps below.
  • Freshness: your search reads a shared index of the boards' open jobs. A separate maintenance run re-reads the index stalest parts first, and every run reports the age of the oldest part it used (public index manifest, 2026-10-15 11:33 UTC: 236 of its 311 parts were under 72 hours old and 52 under 30 hours; the oldest was 153 hours old). Parts of the index more than 30 hours old, or that the last refresh could not fully read, are searched live as well, for up to 5 seconds: parts the refresh read only partly first, then the oldest (set liveTopUpSeconds to change it; 0 switches it off); the search is always answered from the index first, and boards the live read does not reach keep their indexed answer, whose age the run reports (up to 4 minutes of live reading only when no part of the index is usable). Then every match is re-read from the employer's own job board, so closed jobs are dropped and descriptions, dates and apply links are current. Each run reports the index age, and how many boards it read live, in its status line and in RUN_SUMMARY.
  • Speed and price: on the latest board bench (2026-10-09 20:52 UTC, build 0.6.7) a search took 18.4 to 22.6 s on Apify (20.1 s on average). The Actor charges a flat $0.003 per search plus $0.004 per job.
  • Salary floor: set minSalary (annual, e.g. 150000) to keep only jobs whose posted pay range reaches it. Jobs below it, paid in another currency, or with no pay stated (unless you turn on includeJobsWithoutSalary) are left out and cost nothing. Board test run 2026-10-10 12:19 UTC (build 0.7.4; Software Engineer, posted in the last 30 days, minSalary 150000, maxJobs 20): 20 jobs in 8.6 s, charged as 1 search plus 20 jobs; the 11 matches left out on the way (1 paying below the floor, 9 with no pay stated, 1 paid in another currency) were not charged. The most-used career-site search Actor (1,565 monthly users) can keep jobs that state a salary but has no minimum-pay setting (its input schema, checked 2026-10-10). A job passes when the top of its range reaches the floor, so an $80,000 to $210,000 range passes a $150,000 floor.
  • Country filter from the employer's own record: locations: ["United States"] (or US, USA, United Kingdom, UK, Germany, DE) matches the job's country as the job system records it: its country field or the job's office list where it has one (Lever, Greenhouse, Workday, SmartRecruiters, Ashby and others), otherwise the country named in its place text. Every row carries country (ISO-2) and countries. This matters because many postings never write the country. Of Palantir's 235 Lever postings with country US, none says "United States" or "USA" in its location (they say "New York, NY", "Washington, D.C."). Of the 476 Anthropic jobs Greenhouse lists under a US office, 467 don't either (public APIs, 2026-10-11). Our Lab's replay against 11 public boards' own APIs (8 Greenhouse, 3 Lever), 2026-10-11: the boards themselves place 2,644 jobs in the US and 396 in the UK. A United States search over the index keeps 2,639 of the US jobs (99.8%) and a United Kingdom search keeps 385 of the UK jobs (97.2%). 99.8% and 100% of what each keeps really is in that country. The text matching used before 2026-10-11 kept 15% and 43%. Codes match only as whole words, so US never matches "Austin" or "business". CA alone means Canada.

Measured against the two most-used career-site search Actors

Our board's Lab bench gave this Actor and two career-site job search Actors on the Apify Store, the most-used one (1,565 monthly users) and a newer one (113 monthly users), the same four searches. It then checked each answer against the employer's own job board: job found, company, location, posted date, department, and the lowest salary stated in the posting. Bench run 2026-10-09 20:52 UTC, build 0.6.7:

SearchThis ActorMost-used (1,565 monthly users)Newer (113 monthly users)
Greenhouse job at a large employer, posted 2026-10-075 of 5 checks4 of 54 of 5
Ashby job at a small startup, pay range from the posting text5 of 54 of 55 of 5
Workday job at a large employer, pay range from the posting text4 of 40 of 4 (job not returned)4 of 4
Personio job at a small company, posted 2026-10-075 of 53 of 53 of 5
All checks matched19 of 19 (100%)11 of 19 (58%)16 of 19 (84%)
Fields filled91%53%92%
Searches that returned the job4 of 43 of 44 of 4
Run time per search (average)20.1 s1.9 s2.1 s
Price in these runs, per 1,000 jobs$7.05$12.03$3.29

Known gap 2026-10-10, fixed 2026-10-11: on 2026-10-10 10:49 UTC (board test run, same code as the bench) the Workday search in the table returned 0 jobs. The index part that holds that employer's board (one of 3 parts with 60 large Workday employers, among them NVIDIA, Target and Salesforce) had held 0 jobs since 2026-10-08, and the 5-second live read went to the oldest parts first, so it never reached that board. Since then the live read goes first to parts the last refresh could read only partly, and the index is refreshed on a rotation, stalest parts first (2026-10-11 09:08 UTC: none of the 311 parts held 0 jobs). Our re-run of the same search on 2026-10-11 09:08 UTC, with the code of the current Store build, returned the job again (1 job in 25.1 s; that board was read live, as its index part still holds only 13 of its 20 boards). A board the index lacks can still be missed when the 5-second live read does not reach it; the status line says how old the index is and how many boards were read live, and extraBoards (e.g. https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite) always reads a board live.

Both alternatives answer faster (they serve from their own databases) and the newer one filled slightly more fields and cost less in these runs. Our price per 1,000 jobs is high here because each search returned one job, so the $0.003 search fee counts in full; at 1,000 jobs a run costs $4.003. Four searches are a small sample; later builds have not been benched again yet.

Use it as a job postings API

Get your Apify API token (free account; Apify Console > Settings > API & Integrations), then:

Python (pip install "apify-client>=3.2")

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("hiver/career-site-job-search").call(run_input={
"keywords": ["data engineer"],
"locations": ["United States"],
"postedWithinDays": 7,
"maxJobs": 50,
"includeDescription": False,
})
for job in client.dataset(run.default_dataset_id).iterate_items():
print(job["postedAt"], job["company"], job["title"], job["country"], job["salaryMin"], job["url"])

HTTP (one call, waits for the run and returns the jobs as JSON)

curl -X POST "https://api.apify.com/v2/acts/hiver~career-site-job-search/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"keywords": ["data engineer"], "postedWithinDays": 7, "maxJobs": 20, "includeDescription": false}'

Only jobs whose pay range reaches $150,000 a year: add "minSalary": 150000 to either input ("salaryCurrency": "EUR" for euros; "includeJobsWithoutSalary": true keeps jobs that state no pay, marked salaryKnown: false). Add &format=csv to that URL for CSV. The same input works from JavaScript (apify-client), Make, Zapier, n8n and Apify schedules. For a daily alert, see Alerts below or the free GitHub Actions template hiver-data/career-site-job-alerts (daily search, de-duplicated jobs.csv, optional Slack or Discord post).

Unofficial, not affiliated with any job-system vendor or employer. It reads only the public job-board data that companies publish for anyone to see. No login, no API key, no applicant data.

What you get

  • One row per job, the same fields from every source: source, company, companySlug, boardUrl, jobId, title, url, applyUrl, department, team, employmentType, experienceLevel, workplaceType, isRemote, location, locations, city, region, country (ISO-2, null when no place names one), countries (all of a multi-office job's), postedAt, updatedAt, salaryMin, salaryMax, salaryCurrency, salaryInterval, salaryKnown, descriptionText, descriptionHtml.
  • Salary floor: set minSalary (annual) to keep only jobs whose posted pay range reaches it (top of the range, or the single figure). Hourly, weekly and monthly pay is converted to a year for the comparison only (hour x 2080, month x 12); the output keeps the posted numbers. salaryCurrency (default USD) limits the comparison to that currency, with no exchange rates. Jobs with no pay stated are dropped unless includeJobsWithoutSalary is on (then salaryKnown is false). Dropped jobs are never delivered or charged; the run status says how many were dropped. Because most postings state no pay, expect a small share of matches to pass.
  • Fields a source does not publish are null (for example most boards publish no structured salary; where the posting text states a pay range it is read into the salary fields).
  • A RUN_SUMMARY record in the run's key-value store: boards scanned per source, boards that failed, rate-limit hits, run time.

The board directory

The Actor ships with a directory of company job boards. It was built on 2026-10-08 from the open Common Crawl web index (crawls CC-MAIN-2026-25, -30, -34 and -39) plus the MIT-licensed company lists of the open-source project Feashliaa/job-board-aggregator. Every candidate was then checked against its public API or public sitemap, and only boards that answered with at least one open job on that day were kept.

SourceBoards in the directoryOpen jobs on those boards when builtSearched by default
Greenhouse5,150184,281yes
Ashby3,27067,906yes
Workday (career sites of 1,075 companies)1,609396,272yes
Breezy HR1,22426,215yes
BambooHR1,49011,768yes
Personio (EU)1,36113,987yes
Teamtailor (EU)86014,516yes
Rippling83113,104yes
Lever90636,652yes
iCIMS77999,879yes (not with a posting-date filter)
SmartRecruiters732232,613yes
Oracle Recruiting Cloud (445 companies' hosts)553255,024yes
Recruitee1923,564yes
Pinpoint723,252yes
Workable1,72988,664no, add workable to sources (see Limits)

That is 19,029 boards searched by default and 20,758 including Workable. Oracle: a company can run several career sites, so 553 sites are listed on 445 distinct Oracle hosts (sites of one host with the same job count are counted once). Workday: 1,194 company hosts were found in Common Crawl, 1,075 answered with an open job, and a company can run several career sites.

What this means for you:

  • It is not every company. It is the boards that show up in open web data and answered when checked. SAP SuccessFactors and Taleo are not covered (SuccessFactors career sites have no public search API and no directory could be built from open data; only 11 of them turned up). Workday, Oracle or iCIMS companies that do not appear in Common Crawl are missing too. Use extraBoards to add a board by its address (Workday, Oracle, iCIMS, Personio, Teamtailor, BambooHR, Breezy, Pinpoint, Rippling and the other addresses are recognised).
  • Boards that have closed since 2026-10-08 are skipped silently; boards opened since then are missing until the directory is rebuilt.
  • Job counts change daily: the "open jobs when built" column is a snapshot, not a promise.
  • iCIMS and BambooHR list pages carry no description; the Actor reads each matching posting page for it. iCIMS publishes no real posting date (only a rolling placeholder), so postedAt is empty for iCIMS jobs and they are left out when you set postedWithinDays; the sitemap's last-modified time is in updatedAt.
  • Oracle and Workday search by keyword on their servers; the other sources return their whole board and the Actor filters it.

How to use

  1. Enter keywords, e.g. data engineer, product designer. A job matches when its title contains a keyword at the start of a word (so ai finds "AI Engineer" but not "Email Manager"). Phrases work.
  2. Optionally add a location (Berlin, United Kingdom), remoteOnly, postedWithinDays, words to exclude from the title, and which job systems to search.
  3. Set maxJobs (you are charged per job delivered, so this is also your spending cap).
  4. Run. Download the dataset as JSON, CSV or Excel, or read it through the API.

Alerts: turn on onlyNew, choose a monitorId such as backend-berlin, and schedule the Actor daily. The first run delivers every current match and remembers it; later runs deliver and charge only jobs not delivered before under that monitor ID. Prefer GitHub? The free template hiver-data/career-site-job-alerts runs the search daily from GitHub Actions and keeps a de-duplicated jobs.csv.

Input

FieldWhat it does
keywordsJobs whose title contains any of these. Add searchDescriptions to match the full text too.
titleTerms, excludeTermsStricter title requirement, and title words to drop.
locationsA country name or code (United States, US, UK, Germany) matches the job's country (ISO-2, from the board's own country field or office list; whole words only). CA alone means Canada. Any other term (Berlin, Austin, Remote) matches whole words in the location text.
remoteOnlyJobs the company marks as remote, or whose location says remote.
postedWithinDaysPublished in the last N days (jobs with no publish date are dropped when this is set).
minSalary, salaryCurrency, includeJobsWithoutSalarySalary floor: keep jobs whose posted pay range reaches this annual amount in this currency (default USD); hourly and monthly pay is annualised for the comparison. Jobs with no pay stated are dropped unless the third option is on. Dropped jobs are not charged.
sourcesWhich job systems to search (Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee, Workday, Oracle, iCIMS, Personio, Teamtailor, BambooHR, Breezy, Pinpoint, Rippling, Workable). Empty means all except Workable.
maxJobs, maxJobsPerBoardTotal cap, and cap per company.
maxBoardsPerSource, maxMinutesScan only the first N boards of each system, or stop after N minutes, and deliver what was found.
extraBoardsBoard addresses not in the directory, e.g. https://jobs.lever.co/spotify. Scanned first.
onlyNew, monitorIdNew-since-last-run alerts.
includeDescriptionFull descriptions (default on; same price either way).

Example input (also the default prefill):

{
"keywords": ["data engineer", "machine learning engineer"],
"postedWithinDays": 7,
"maxJobs": 50
}

Speed and what a run costs

How a search works. A separate maintenance Actor (career-jobs-index-refresh, run on the publisher account) re-reads the 19,029 boards in turn, stalest parts of the index first, and writes the open jobs (title, company, location, date, links) to a public index; each search run reports the age of the oldest part it used. A search then (1) scans the titles of all ~1 million indexed jobs for your keywords, location and date, (2) takes the newest matches up to maxJobs, and (3) re-reads each match from the employer's own job board, which drops jobs closed since the refresh and adds the description, salary and current date. If a part of the index is older than 30 hours or missing, those boards are also read live (capped at liveTopUpSeconds, 5 s by default: parts the last refresh read only partly first, then the oldest); if the whole index is unreachable the Actor falls back to a live sweep capped at 4 minutes (set maxMinutes to change it) and says so in the status line.

Local measurements (2026-10-08, 4-core machine, index read from disk, so no download time):

  • 50 jobs for data engineer / machine learning engineer, last 7 days, with descriptions: 4.7 s.
  • 1,000 jobs for engineer, no descriptions: 27 s. 525 jobs for the two data keywords with maxJobs 1000: 23 s.
  • A search with no match: 1.4 s. Peak memory 300 to 450 MB.
  • Full index refresh of all 19,029 boards: 771 s, 1.04 million jobs from 18,873 boards that answered (the rest were closed or empty that day).
  • For comparison, the old live sweep of the same boards took 358 s locally and an estimated 15 to 16 minutes on Apify.

Cloud measurements on Apify (1 GB, board bench 2026-10-09 20:52 UTC, build 0.6.7): four searches took 18.4 to 22.6 s each (20.1 s on average) and used $0.00006 to $0.0017 of compute. A typical status line: "1 jobs in 17.0s: 19029 boards from the daily index (oldest part 31.8 h old, 0 closed jobs dropped), 401/489 boards swept live - live top-up ended at its 5.0s limit". An older build (0.5.1, bench 2026-10-08 09:37 UTC) read stale boards live for up to 60 s and took about 69 s per search; the 5-second live top-up replaced that.

  • Index size: about 25 MB of title files plus 100 MB of job records; a search downloads the title files (about 25 MB, compressed) and only the record chunks that hold your matches.
  • Live mode (useIndex off, searchDescriptions on, or maxBoardsPerSource set) reads the boards directly as before; it is slower (minutes) and meant for description search and for boards you add with extraBoards.

Coverage limits

  • Workable answers HTTP 429 after a few dozen requests from one address, so a polite sweep of its 1,729 boards is not possible at this speed. It is off by default; add workable to sources to try it (two requests at a time, it gives up when the host keeps refusing and says so).
  • SAP SuccessFactors and Taleo are not covered (see the directory section).
  • Each source returns only what the company publishes: most boards have no salary, and some (Rippling, BambooHR, iCIMS list pages) carry less structured data than others.

Pricing

Pay per event, no subscription. You pay $0.003 per search and for jobs delivered to the dataset; a company that is not found or has no open jobs costs nothing. maxJobs caps what a run can charge, and you can also set a maximum cost per run in Apify.

Apify planPer jobPer 1,000 jobs
Free / Bronze$0.004$4.00
Silver$0.0036$3.60
Gold$0.0032$3.20

Plus a flat $0.003 per search (Silver $0.0027, Gold $0.0024), charged once per run whatever the number of matches. Apify's own run-start event is $0.00005.

Worked example: A run that returns 1,000 jobs costs $4.003 on Free/Bronze ($3.20 on Gold); a search with no match costs $0.003.

Limits (honest list)

  • Workday: the search is done by Workday's own job search, which ranks by relevance and may return jobs that match only part of your phrase; results are then checked against the title here, like for every other system. Workday list rows show "Posted N days ago" only, so the date is day-precise, and "Posted 30+ days ago" jobs have no date until the posting page is read (done automatically when a location, remote filter or a window over 29 days is set). Workday returns at most 2,000 results per search. Workday workplaceType/isRemote come from the posting page and are only filled when a location, remote filter or descriptions are requested. Salary comes from the pay range stated in the posting text.
  • Country filter: a job whose job system gives only a city (London, Munich, Vancouver, BC) and no country has country: null, and a country term does not match it. Add the city as a second term (["United Kingdom", "London"]). In an index search, Greenhouse jobs whose location text names no country are checked against the posting's office list when the search re-reads them, up to the 400 newest per search. A very broad country search (no keyword) can miss older jobs past that cap. The replay above covers Greenhouse and Lever boards only.
  • Titles are matched as text, not by meaning: "software developer" will not find "programmer".
  • SmartRecruiters boards are filtered on SmartRecruiters' side by keyword, which can match on more than the title; results are then checked against the title again here. SmartRecruiters descriptions need one extra request per matching job.
  • searchDescriptions is slower (Greenhouse boards are downloaded in full) and is not available for SmartRecruiters.
  • Posting dates are what the employer's job system reports. Some systems report "last updated" rather than "first published".
  • Workable limits request rates strictly. In the 2026-10-07 full-sweep test Workable answered 429 from the test machine and was skipped entirely (the Actor stops asking after repeated refusals, it does not try to get around the limit). A run can come back with Workable partly or entirely skipped; the status message and RUN_SUMMARY say when. Workable boards in the directory: 1,729.
  • Salary is only present where the company publishes it in its job post: structured pay when the board has it, otherwise a range stated in the posting text (several ranges, e.g. per level or location: the lowest minimum and highest maximum of those in the first range's currency and period). Text without a clear range gives null, never a guess. This works with includeDescription off too.

FAQ

Does it need a login or API key? No. It reads public data only.

Can I call it as a job postings API? Yes. Each call is one Actor run that returns the jobs as JSON, CSV or Excel: use Apify's HTTP endpoint run-sync-get-dataset-items or its Python and JavaScript clients (examples under "Use it as a job postings API"). You need your own Apify token; you pay per search and per job delivered.

Coming from JobSpy (python-jobspy)? JobSpy searches job boards such as LinkedIn and Indeed; this Actor searches employers' own career sites. The free script hiver-data/career-sites-for-jobspy calls it from Python and returns a pandas DataFrame with the same 34 columns, in the same order, as jobspy.scrape_jobs() (checked against python-jobspy 1.3.0), so you can pd.concat both results.

Can I filter jobs by salary? Yes. minSalary keeps only jobs whose posted pay range reaches that annual amount (top of the range, or the single figure), in the currency you set; jobs without stated pay are dropped or kept and flagged (includeJobsWithoutSalary), and dropped jobs are not charged. Pay comes from the employer's own posting: structured pay where the job system has it, otherwise a range stated in the posting text. Most postings state no pay, so expect a smaller result set.

Can I get only jobs in one country? Yes. Put the country in locations (United States, US, United Kingdom, UK, Canada, Germany). It matches the country the employer's job system records for the job (country field or office list, else the country its place text names), and each row's country field tells you which. In the 2026-10-11 replay of 11 public Greenhouse and Lever boards, that kept 99.8% of the US jobs and 97.2% of the UK jobs. See the first section for details and the limits list for the gaps.

What are the rate limits? The Actor reads at a polite pace, retries when a source slows it down and stops asking a source that keeps refusing; it never tries to get around a limit. The run log says what was skipped.

How many jobs can I get per run? As many as the sources list, up to your maxJobs cap. Jobs closed by the employer disappear from the source and from your next run.

Is it affiliated with the job systems or companies? No. Unofficial, not affiliated with or endorsed by any job-board vendor or employer; it reads only public job data and no applicant or employee data.

Something is broken or a field is missing? Open an issue on the Actor page.