ATS Jobs Scraper: Greenhouse, Lever, Ashby, Workable, Recruitee avatar

ATS Jobs Scraper: Greenhouse, Lever, Ashby, Workable, Recruitee

Pricing

from $1.10 / 1,000 jobs

Go to Apify Store
ATS Jobs Scraper: Greenhouse, Lever, Ashby, Workable, Recruitee

ATS Jobs Scraper: Greenhouse, Lever, Ashby, Workable, Recruitee

Scrape jobs from Greenhouse, Lever, Ashby, Workable and Recruitee boards via official public APIs. Get titles, locations, salaries and apply links, filter roles, and monitor new job postings.

Pricing

from $1.10 / 1,000 jobs

Rating

0.0

(0)

Developer

Ad Astra Connect

Ad Astra Connect

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

ATS Jobs Scraper: Greenhouse, Lever, Ashby, Workable and Recruitee job boards

Scrape open jobs from Greenhouse, Lever, Ashby, Workable and Recruitee company career boards in one run. ATS Jobs Scraper reads each platform's official public job board API and returns one clean, consistent dataset: job title, company, department, location, remote status, employment type, salary range, posting date, description and apply link. No login, browser or proxy, so runs are fast and cheap.

Turn on monitoring and the Actor returns only jobs that are new since the last run, which makes it a simple job alert feed for recruiting, sales prospecting, market research or your own job search.

Why use ATS Jobs Scraper?

  • Five ATS platforms, one schema. Mix Greenhouse, Lever, Ashby, Workable and Recruitee boards in the same input and get identical fields for every job.
  • Official public APIs only. The same endpoints company career pages use. No HTML parsing that breaks when a page redesign ships.
  • New-job monitoring built in. Schedule it daily and pay only for jobs you have not seen before.
  • Structured salaries. Uses structured compensation where the ATS provides it (for example Ashby), with conservative text extraction as a fallback.
  • Filters before billing. Keyword, exclusion, location, remote, department and date filters run before output, and you pay only for rows you receive.
  • Fault tolerant. One broken or moved board is reported in the run summary and never fails the whole run.

Use cases

  • Recruiting and talent intelligence: track hiring at competitor or target companies by team and location.
  • Sales and lead signals: spot companies hiring for roles that indicate a need for your product (for example "data engineer" or "security").
  • Job boards and newsletters: feed a niche job board or weekly digest with fresh postings from a curated company list.
  • Market research: count openings by department, location or remote policy over time.
  • Personal job alerts: watch a shortlist of companies and get only new matching roles.

What data can you get

FieldsData
idStable ats:companySlug:nativeId identifier. A URL hash is used if an API has no native ID.
ats, companySlug, companyNameSource and company. The board slug is used when the API does not provide a company display name.
title, department, teamJob title and available organizational categories.
location, locations, countryPrimary location, all available location strings, and country when supplied.
isRemote, workplaceTypeRemote flag and onsite, hybrid, remote, or null. Unknown remote flags are null.
employmentType, employmentTypeRawfull_time, part_time, contract, temporary, internship, other, or null, plus the source value.
salaryMin, salaryMax, salaryCurrencyStructured compensation when available, otherwise conservative extraction from job text. Unknown values are null.
salaryInterval, salaryTextyear, month, week, day, hour, or null, and an available compensation summary or matched snippet.
url, applyUrlPublic job page and application link when supplied.
publishedAt, updatedAtISO 8601 dates, or null. A created date is used when a published date is unavailable.
descriptionTextPlain text with paragraph breaks, included by default.
descriptionHtmlOptional safe paragraph HTML rebuilt from the cleaned description.
isNew, scrapedAtNew-job flag in monitoring mode, otherwise null, and the collection timestamp.

The dataset's overview table shows the company, job title, location, remote status, employment type, salary, posting date, URL and ATS. Export JSON, CSV, Excel or other formats supported by Apify datasets.

How to use

  1. Open the Actor input and enter companies as ATS shorthand, job board URLs or bare slugs.
  2. Add optional keyword, location, department or remote filters.
  3. Set the maximum number of results and start the Actor.
  4. Open the dataset to review or export jobs. Open RUN_SUMMARY in the default key-value store to inspect target counts and errors.
  5. To monitor jobs, enable onlyNewJobs, keep the same monitorKey, and schedule repeated runs.

Empty programmatic input {} uses greenhouse:stripe and a maximum of 1,000 results. The input editor also offers a multi-company example.

Company formats

  • greenhouse:stripe, lever:spotify, ashby:ramp, workable:huggingface, recruitee:your-company
  • https://boards.greenhouse.io/stripe, https://job-boards.greenhouse.io/stripe or https://job-boards.eu.greenhouse.io/your-company
  • https://jobs.lever.co/spotify or https://jobs.eu.lever.co/your-company
  • https://jobs.ashbyhq.com/ramp
  • https://apply.workable.com/huggingface
  • https://your-company.recruitee.com
  • notion: try Greenhouse, Lever, Ashby, Workable and Recruitee in that order, taking the first board with at least one listed job. The selected source and probes appear in RUN_SUMMARY. Probes do not emit or bill rows.

Lever tries the global API first and tries its EU API on HTTP 404. A supplied EU board URL follows this same lookup rule. Greenhouse URLs, including EU board URLs, use the specified public boards-api.greenhouse.io endpoint.

Input example

{
"companies": [
"greenhouse:stripe",
"lever:spotify",
"ashby:ramp",
"workable:huggingface",
"notion"
],
"keywords": ["engineer"],
"excludeKeywords": ["intern"],
"locations": ["Toronto", "Canada", "Remote"],
"remoteOnly": false,
"searchInDescription": false,
"maxJobsPerCompany": 15,
"maxResults": 60,
"requestDelayMs": 500
}

Input reference

InputDefaultBehavior
companies["greenhouse:stripe"]Required array of non-empty company strings. Invalid individual targets are isolated.
keywords, excludeKeywords[]Case-insensitive substring matching. ANY keyword includes a job; ANY exclusion removes it.
searchInDescriptionfalseApply keyword inclusion and exclusion to title and description together.
locations[]Match ANY substring in ANY location. Explicit remote status also matches Remote.
remoteOnlyfalseKeep only explicitly remote jobs. Hybrid roles are excluded.
departments[]Match ANY substring in department or team.
postedWithinDays0Published/created date window. Zero disables it; undated jobs are kept.
includeDescriptiontrueInclude plain text description. Filtering and salary extraction work even when this is false.
includeDescriptionHtmlfalseInclude sanitized paragraph HTML. Original attributes, links and layout are removed.
onlyNewJobsfalseOutput jobs absent from the previous full snapshot for this monitor.
monitorKey"default"Separate independent monitoring baselines.
maxJobsPerCompany0Per-company output limit after filters and new-job detection; zero is unlimited.
maxResults1000Positive integer; hard cap on billable output rows.
requestDelayMs500Minimum per-host request spacing. Lever always uses at least 1,000 ms. Robots crawl delays can raise it.

Filter groups are combined with AND. Title matching is a substring search, so engineer also matches engineering. Limits apply after filtering. Duplicate entries pointing to the same ATS and slug do not produce duplicate rows.

Output example

Illustrative job data, with the same schema as a real result:

{
"id": "lever:example:bc8214ab-9810-4050-89ba-123456789abc",
"ats": "lever",
"companySlug": "example",
"companyName": "example",
"title": "Senior Backend Engineer",
"department": "Engineering",
"team": "Platform",
"location": "Toronto, Canada",
"locations": ["Toronto, Canada", "Remote Canada"],
"country": null,
"isRemote": true,
"workplaceType": "remote",
"employmentType": "full_time",
"employmentTypeRaw": "Full-time",
"salaryMin": 120000,
"salaryMax": 150000,
"salaryCurrency": "CAD",
"salaryInterval": "year",
"salaryText": null,
"url": "https://jobs.lever.co/example/bc8214ab-9810-4050-89ba-123456789abc",
"applyUrl": "https://jobs.lever.co/example/bc8214ab-9810-4050-89ba-123456789abc/apply",
"publishedAt": "2026-10-01T10:00:00.000Z",
"updatedAt": null,
"descriptionText": "Build reliable services.\n\nWork with the platform team.",
"isNew": true,
"scrapedAt": "2026-10-20T12:00:00.000Z"
}

How much does it cost to scrape ATS jobs?

This Actor uses pay per event pricing: $1.50 per 1,000 jobs returned (Apify Store discount tiers pay less). The price on the Store page is authoritative. Platform compute is included, so you pay for the jobs you receive plus Apify's small per-run start fee, nothing else.

Example runJobs returnedApproximate cost
5 companies, filtered to engineering roles50about $0.08
20 companies, all roles1,000about $1.50
Daily monitoring of 20 companies, about 30 new jobs per day900 per monthabout $1.35 per month

What you are charged for: each job row written to the dataset is one job event. Auto-detection probes, failed boards, filtered-out jobs and previously seen jobs in monitoring mode are free. Use maxResults to cap a run, and set a maximum cost per run in Apify; the Actor stops cleanly when that limit is reached.

Incremental runs / monitoring

Set onlyNewJobs: true and choose a stable monitorKey. State is stored in the named key-value store ats-jobs-scraper-state, under a SHA-256-derived monitor key, with separate ID sets for each ATS and company slug. Ordinary runs with monitoring disabled neither read nor update this state.

The first monitoring run returns all current matching jobs, subject to the output limits. You can make this first run cheap by setting a small maxResults. The Actor still fetches full snapshots and saves every current ID, including jobs hidden by filters or output limits. Later runs therefore return only jobs introduced after that baseline. Changing filters does not make an existing job new.

After a successful full fetch, IDs absent from that snapshot are removed. A closed job that later reappears is new again. Changed descriptions or titles with the same ID are not new. Failed or incomplete fetches do not replace the company's baseline. Boards not included in a run retain their stored baseline.

A spending-limit stop ends further work. Successfully processed companies may have their baselines updated; unprocessed companies keep their earlier state. Run the same monitor serially to avoid concurrent writes. Use another monitorKey, or delete that monitor's named-store record, to start over.

Scheduling and integrations

Use Apify schedules for periodic checks and webhooks to trigger a downstream process when a run finishes. Start runs and download datasets through the Apify API. Connect results to Make, Zapier or n8n for notifications, spreadsheets and recruiting workflows. AI agents can call the Actor through Apify's MCP integration and consume the normalized job records.

This Actor uses only official public GET endpoints intended for company career pages. It does not log in, send cookies, collect applicant profiles, or submit applications. It identifies itself, checks the API host's robots.txt before fetching, and obeys disallowed paths and crawl delays. Following RFC 9309, robots.txt redirects are followed (for example from a Recruitee subdomain to the company's own careers domain), a robots.txt that is unavailable with a 4xx status means no restrictions, and a server error or HTML response causes the target to be skipped. SmartRecruiters is intentionally unsupported because its API robots policy disallows generic crawlers.

The output is limited to job fields. It excludes recruiter, hiring-manager and applicant objects and arbitrary metadata, and redacts email addresses, phone numbers and detected individual names in job copy. Safe description HTML is rebuilt from redacted text. Automated name detection has limitations; review descriptions before redistribution. You are responsible for your use of the data, applicable terms and legal requirements.

Public API references: Greenhouse Job Board API, Lever Postings API, Ashby Job Postings API. Workable uses its public widget endpoint and Recruitee uses its public careers offers endpoint, as listed in the source adapters.

Limitations

  • Only the five listed ATS platforms and their public jobs are supported. No private jobs or authenticated APIs are used.
  • Companies can change ATS providers, close boards or change API formats. Auto-detection takes the first non-empty board and cannot guarantee it belongs to the company you intended.
  • An explicit board with zero jobs is a successful fetch. Auto-detection requires at least one job.
  • API access depends on each provider's current robots policy and public API. If a provider changes either, affected targets are skipped and reported in RUN_SUMMARY rather than failing the whole run.
  • Ashby's public API does not return a company display name, so companyName is the board slug for Ashby jobs.
  • Workable's widget often provides job summaries without descriptions, salaries or update dates. No detail-page scraping is performed to fill these gaps.
  • Company names, dates, country, workplace type and compensation may be absent. Null values are deliberate. Lever and Ashby commonly use the slug as the company display name.
  • Salary extraction is conservative. Structured salary fields take priority. Multiple money ranges or conflicting currencies leave numeric fields null. A bare dollar sign does not identify a currency. No currency conversion or annualization is performed.
  • Full list snapshots are fetched before filters or output limits. Lever uses paginated requests; the other specified endpoints return full lists. Normal runs can stop at the overall output cap; monitoring continues through all targets unless the spending limit is reached.
  • Only complete valid snapshots update monitoring state. The state is an ID baseline, not a complete job archive or a guarantee of downstream delivery.
  • Requests have a 20-second timeout and up to four retries with exponential backoff and jitter for transient errors. Retry-After is honored. Targets run sequentially, with one request at a time per host.

FAQ

Do I need an API key or company account? No. Only public job board endpoints are used.

Can I use a company homepage? Use its supported ATS board URL, ats:slug, or the board slug. Arbitrary company websites are not crawled.

Why did a company return no results? Check filters and RUN_SUMMARY. The board might be empty, incorrect, migrated, blocked by robots, or temporarily unavailable.

Will the second monitoring run be empty? Yes, if no new job IDs appeared on successfully fetched boards. The first run establishes the baseline even when output limits hide some jobs.

Can I get raw HTML? The optional HTML field contains safe paragraphs rebuilt from redacted text. It omits original markup, attributes and embedded content.

How do I find a company's board? Open the company's careers page and click any job. The job URL shows the ATS and slug, for example boards.greenhouse.io/stripe or jobs.lever.co/spotify. You can paste that URL directly, or just enter the slug and let auto-detection find it.

How fast is it? A typical board of a few hundred jobs takes a few seconds. Lever boards are paged and rate-limited politely, so very large Lever boards take longer.

Can I get jobs from Workday, SmartRecruiters, iCIMS or LinkedIn? Not in this Actor. It only uses documented public job board APIs, and SmartRecruiters' API robots policy disallows generic crawlers.

Can one bad company fail the entire run? Per-target failures are isolated and recorded. The run fails when every attempted target fails. Invalid top-level input also fails clearly.

Support

Open an issue in the Actor's Issues tab. Include the company entry, relevant input and run link or RUN_SUMMARY error. Do not include credentials or personal information.

Disclaimer

Greenhouse, Lever, Ashby, Workable and Recruitee are trademarks of their respective owners. This Actor is an independent tool and is not affiliated with, sponsored by or endorsed by any of them. Nothing in this README is legal advice.