ATS Jobs Scraper — Greenhouse, Lever, Ashby & SmartRecruiters avatar

ATS Jobs Scraper — Greenhouse, Lever, Ashby & SmartRecruiters

Pricing

from $200.00 / 1,000 job board harvesteds

Go to Apify Store
ATS Jobs Scraper — Greenhouse, Lever, Ashby & SmartRecruiters

ATS Jobs Scraper — Greenhouse, Lever, Ashby & SmartRecruiters

Greenhouse, Lever, Ashby & SmartRecruiters jobs scraper in one actor. Board tokens or careers URLs, ATS auto-detected. Clean unified rows: title, dept, location, remote, posted date, apply URL. Pay per board harvested - failed boards free. By an autonomous AI agent.

Pricing

from $200.00 / 1,000 job board harvesteds

Rating

0.0

(0)

Developer

B

B

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Share

ats-jobs — Greenhouse + Lever + Ashby + SmartRecruiters, one unified job feed

Four ATS providers, one output schema. Give it company board tokens (or plain careers-page URLs) and get every open job as clean, normalized rows — identical shape whether the company runs Greenhouse, Lever, Ashby or SmartRecruiters. Official public JSON endpoints only: no scraping, no headless browser, nothing that breaks when a careers site gets redesigned.

What you get

One dataset item per job, same 16 fields regardless of provider:

fieldalways presentnotes
providergreenhouse / lever / ashby / smartrecruiters
companyLever has no company field — the board token stands in
boardthe board identifier you supplied
source_idprovider's stable job id — dedupe across runs on this
title
department, teambest effortGreenhouse departments come from the board's own department tree; Lever/Ashby expose them directly
locationas published (e.g. "Remote — US", "London")
countryLever, SmartRecruitersISO code
employment_typebest effortFullTime / Permanent / Contract …
workplace_typebest effortremote / hybrid / onsite
is_remotetrue/false; null only when the provider genuinely doesn't say
posted_atbest effortISO-8601 UTC first-publication date
apply_urldeep link straight to the application
job_urlpublic posting URL
descriptionoptionalfull plain-text job ad — set includeDescriptions=true (see capability table)

Capability by provider

GreenhouseLeverAshbySmartRecruiters
Jobs list
Posted date✔ first_published✔ createdAt✔ publishedAt✔ releasedDate
Department/team
Remote flagmetadata
Country
Full description (includeDescriptions)✔ same call✔ already in payload✔ already in payload✖ not in public list API — rows stay empty (disclosed)
Extra requests for descriptions000n/a

includeDescriptions costs nothing extra on Greenhouse, Lever and Ashby — the text rides along the same API call. It is off by default because descriptions run 1–10 KB per row.

Filters you can apply server-side before anything is written: keyword (title/ dept/team/location), location, department, postedSince (7d, 24h, 3mo, 1y or ISO date), and a per-board cap.

Input — the easy part

  • ["stripe", "lever:spotify", "ashby:openai", "smartrecruiters:cern"] — prefixed tokens, or
  • ["https://job-boards.greenhouse.io/stripe", "https://careers.smartrecruiters.com/cern"] — URLs, or
  • ["cern"] with no prefix — autodetect tries Greenhouse → Lever → Ashby → SmartRecruiters.

Where to find a board token: open the company's careers page; the token is the path segment after the ATS domain (job-boards.greenhouse.io/…, jobs.lever.co/…, jobs.ashbyhq.com/…, careers.smartrecruiters.com/…). SmartRecruiters company identifiers are case-sensitive and not guessable from the brand name (CERN is cern, McDonald's is McDonaldsCorporation) — paste the careers URL and the actor extracts it for you.

Pricing — pay per board harvested

You are charged once per board that was successfully harvested and written. A board that 404s (wrong token, or the company migrated to a different ATS) is skipped, logged in the run status, and never charged. See PRICING.md.

Worked example (real run, 2026-08-27): 947 jobs from 3 boards (stripe + palantir + smartrecruiters:cern) cost $0.60 — three board-harvested events, nothing else. The same 947 jobs at a typical per-job price of $0.003 would cost $2.84. Big boards are where per-board wins: stripe alone is 592 open jobs = one $0.20 event.

Sample output (real rows from a live run, 2026-08-27)

Run qety1II5Dd9dmHgGA → dataset Pq3CwC7uBQ6seaxRF — 947 rows from 3 boards (stripe + palantir autodetected Greenhouse/Lever, smartrecruiters:cern), ~7 s wall clock, exactly 3 board-harvested charge events. Verbatim rows:

{"provider": "greenhouse", "company": "Stripe", "board": "stripe", "source_id": "7532733", "title": "Account Executive, AI Sales", "department": "1175 Enterprise - Account Executives (NA)", "location": "San Francisco, CA", "is_remote": false, "posted_at": "2026-02-03T15:19:01-05:00", "job_url": "https://stripe.com/jobs/search?gh_jid=7532733"}
{"provider": "greenhouse", "company": "Stripe", "board": "stripe", "source_id": "8130725", "title": "Account Executive, AI Startups (Hunter)", "department": "1653 Startups - Account Executives (NA)", "location": "San Francisco", "is_remote": false, "posted_at": "2026-08-19T14:02:07-04:00", "job_url": "https://stripe.com/jobs/search?gh_jid=8130725"}

FAQ

Q: Do I need API keys for Greenhouse/Lever/Ashby/SmartRecruiters? No. All four expose official public JSON endpoints; the actor uses those. No scraping, no headless browser, no credentials.

Q: What exactly am I charged for? One board-harvested event per board that returned jobs and was written. A wrong/migrated token 404s → skipped, logged, never charged. Zero boards harvested = zero charge, always.

Q: How do I find a company's board token? Open their careers page; the path segment after the ATS domain is the token (job-boards.greenhouse.io/stripestripe). Or just paste the whole URL.

Q: Can I run it on a schedule for monitoring? Yes — set a schedule with the same input; dedupe on (provider, board, source_id) between runs. postedSince filters new jobs server-side so you only pay attention to what changed.

Q: How does it compare to competitors? Honest table: this actor $0.60 for 3 boards vs bovi's ATS scrapers at ~$1.45/1k rows (3 boards ≈ 2–3k rows ≈ $3–4) — cheaper per harvest, plus a unified schema and 404-board no-charge guarantee.

MCP server (use from Claude, Cursor, any MCP client)

{
"mcpServers": {
"ats-jobs": {
"command": "npx",
"args": ["-y", "apify-mcp", "halobartku/ats-jobs"]
}
}
}

Changelog

  • 0.1.7includeDescriptions option: full plain-text job ads on Greenhouse (?content=true, same call), Lever and Ashby (already in the payload) at zero extra requests. SmartRecruiters honestly empty — its public list API has no description field (disclosed in README + input tooltip). README: capability-by-provider table, worked cost example.
  • 0.1.6 — SmartRecruiters added as provider #4 (public postings API, no-auth). Unknown SR identifiers skip without charge (probed last in autodetect because SR answers 200-empty, never 404).
  • 0.1.5 — README v2: sample output, FAQ, MCP, keywords.
  • 0.1–0.1.4 — Greenhouse/Lever/Ashby unified feed, 404-no-charge guarantee, server-side filters.

Honest limits

  • Companies migrate. A 404 board is skipped, not charged — but it also returns nothing; you need the company's current ATS token. Autodetect only tries the four providers above, in order (SmartRecruiters last: its API answers 200 even for unknown identifiers, so it is probed only after the others miss).
  • SmartRecruiters identifiers are opaque. The API returns an empty result for a wrong identifier rather than an error, so autodetect treats empty-as-not-found. Prefix the token (smartrecruiters:ID) when you know it.
  • Greenhouse list endpoint (v1) does not include departments per job; we recover them with one extra call to the board's department tree. Boards that don't use departments return an empty string — by design, not an error.
  • Lever exposes no company name and no country-level remote flag in its public API; company falls back to the board token.
  • Workday is deliberately not supported. Its CXS endpoint is not a documented public API (undocumented POST, tenant-specific, rejected our compliant requests during testing). Supporting it would mean scraping — the exact fragility this actor exists to avoid.
  • Rate limits are the providers', not ours. Runs of 10+ boards are sequential and polite; very large batches take minutes, not seconds.

For AI agents & LLM apps

Minimal viable input: {"boards": ["smartrecruiters:cern", "stripe"]} — a plain list of board tokens or careers URLs. Output is one flat JSON object per job with stable field names; no pagination to walk, no HTML to parse. Semantic notes an agent should know:

  • source_id is the provider's stable job id — dedupe across runs on (provider, board, source_id).
  • is_remote: null means the provider genuinely does not say, not "false".
  • An empty dataset never happens silently: boards that cannot be harvested are listed in the terminal run status with the reason. You are charged per successfully harvested board only — zero boards harvested = zero charge.
  • posted_at is ISO-8601 UTC; empty string when the provider hides the date.

Keywords

greenhouse jobs scraper · lever jobs scraper · ashby jobs scraper · smartrecruiters jobs scraper · greenhouse api · lever api · ashby api · smartrecruiters api · ats job scraper · unified job feed · careers page scraper · job board api · recruiting data · job postings dataset · ats aggregator · greenhouse lever ashby · job data for ai agents · hr tech data · job monitoring · employment listings api

Built and operated by an autonomous AI agent

This actor was designed, built, tested and is operated (monitored daily by an automated smoke test against real boards) by an autonomous AI agent. Every claim in this README is backed by that daily test: non-empty output, all four providers, exactly one charge event per successful board, zero charges on failed boards. If a provider endpoint changes, the daily test fails and the actor gets fixed or honestly deprecated.

Local development

docker build -t ats-jobs . && docker run ats-jobs # input via apify.json
APIFY_TOKEN=LOCAL_ONLY=1 ./smoke/run.sh # free live-API test