Most tech companies do not host their own job pages. Their careers page is a thin wrapper around an applicant tracking system (ATS) such as Greenhouse, Lever or Ashby, and those vendors expose public JSON endpoints for job boards. That means you can build a job feed, a hiring-signal tracker or a salary dataset without a headless browser.

Here is how to do it yourself, and how to do it for eight ATS vendors at once with an Apify actor I built.

The DIY route: three endpoints

import requests # Greenhouse gh = requests.get("https://boards-api.greenhouse.io/v1/boards/stripe/jobs").json()["jobs"] print(len(gh), gh[0]["title"], gh[0]["location"]["name"], gh[0]["absolute_url"]) # Lever (EU accounts use api.eu.lever.co) lv = requests.get("https://api.lever.co/v0/postings/spotify?mode=json").json() print(len(lv), lv[0]["text"], lv[0]["categories"].get("location")) # Ashby ab = requests.get( "https://api.ashbyhq.com/posting-api/job-board/openai", params={"includeCompensation": "true"}, timeout=20, ).json().get("jobs", []) print(len(ab), ab[0]["title"]) 

(These are the vendors' public job-board endpoints; field names can change, so check their docs.) The field names differ for every vendor, dates come in different formats, and Workable, Workday, SmartRecruiters, Recruitee and BambooHR each need their own approach. Workday in particular needs a tenant, a datacenter number and a site name.

To find a company's slug, open a job on their careers page and read the URL: boards.greenhouse.io/<slug>, jobs.lever.co/<slug>, jobs.ashbyhq.com/<slug>.

One schema for eight ATS

My ATS Jobs Scraper actor covers Greenhouse, Lever, Ashby, Workable, Workday, SmartRecruiters, Recruitee and BambooHR and normalises them. No-code path: open the actor, paste board URLs (any mix) into companies, set keywords and locations, click Start, export CSV.

Python path:

# pip install apify-client pandas from apify_client import ApifyClient import pandas as pd client = ApifyClient("YOUR_APIFY_TOKEN") run = client.actor("bachiembmt/ats-jobs-scraper").call(run_input={ "companies": [ "https://boards.greenhouse.io/stripe", "https://jobs.lever.co/spotify", "ashby:openai", # source:slug form is accepted  "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite", ], "keywords": ["engineer"], "locations": ["remote", "london"], "postedWithinDays": 30, "maxJobsPerCompany": 25, "includeDescription": False, }) df = pd.DataFrame(client.dataset(run.default_dataset_id).iterate_items()) print(df[["company", "title", "location", "salaryMin", "salaryMax", "url"]].head(20)) 

Output fields: source, company, jobId, title, department, team, location, remote, employmentType, salaryMin, salaryMax, salaryCurrency, postedAt, updatedAt, url, applyUrl, descriptionText.

A daily "new jobs" digest

Schedule the actor in the Console with postedWithinDays: 1, then fetch the last run's dataset:

last = client.actor("bachiembmt/ats-jobs-scraper").last_run(status="SUCCEEDED") for j in last.dataset().iterate_items(): if j["remote"]: print(f'{j["company"]}: {j["title"]} -> {j["url"]}') 

Send that to Slack, email or a Google Sheet from there.

Limits you should know

  • Salary is patchy. Only Ashby, Lever and Recruitee publish pay ranges, and only when the employer fills them in. Greenhouse, Workday, SmartRecruiters, BambooHR and Workable have no public salary field.
  • Workday dates are approximate. The list only says "Posted 3 Days Ago", and 30+ days is reported as 30. With includeDescription you get the exact start date.
  • BambooHR list pages have no date; postedAt is filled only with descriptions on.
  • includeDescription costs one extra request per job on Workable, Workday, SmartRecruiters and BambooHR, at about 1 request per second.
  • You need the company's board slug. The actor does not discover which companies exist, and it only reads companies that use these eight vendors.
  • Only public, published postings. Boards that do not exist are skipped with a warning.

Price

Pay per event, charged only for jobs that pass your filters. It is about $1 per 1,000 jobs at the time of writing (check the Store page; I may adjust it). Scanning 50 company boards with ~40 jobs each is 2,000 jobs, so about $2.

For a handful of companies on Greenhouse or Lever, the DIY snippets are free and fine. I built the actor for the mixed-vendor case where normalising eight formats is the real work. Disclosure: it's my project.

Try it: ATS Jobs Scraper