Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby)
Pricing
Pay per event
Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby)
Scrape job postings from Greenhouse, Lever, and Ashby in one run. Pass a list of company slugs and get a normalised dataset — title, location, department, URL, and description — across all three ATS platforms.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
🎯 What this scrapes
Greenhouse, Lever, and Ashby together power the hiring pipelines of thousands of tech companies. Each platform exposes its own API shape and quirks. This Actor speaks all three natively: it queries the public job board APIs, normalises the fields into one consistent schema, and writes the results to a typed Apify dataset.
Pass a list of {atsType, companySlug} pairs — mix and match platforms in a single run. Get one row per job posting, every time.
Supported platforms:
| ATS | API endpoint style |
|---|---|
| Greenhouse | REST — boards-api.greenhouse.io/v1/boards/{slug}/jobs |
| Lever | REST — api.lever.co/v0/postings/{slug}?mode=json |
| Ashby | GraphQL — jobs.ashbyhq.com/api/non-user-graphql |
🔥 What we handle for you
- 🛡️ Browser fingerprint rotation — requests impersonate real browser TLS handshakes so the target sees a browser, not a bot.
- 🌐 Residential proxy rotation via Apify Proxy — fresh session and exit IP when upstream pushes back.
- 🔁 Retries with exponential backoff on
408 / 429 / 5xx— up to 5 attempts,Retry-Afterhonoured. - 🧱 Rate-limit-aware pacing — we slow down rather than get banned; partial successes surface via a clear status message.
- 🧊 Normalised, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, stable IDs across all three ATS platforms.
- 💰 Pay-Per-Event pricing — you pay only for job postings that land in your dataset.
💡 Use cases
- Talent intelligence pipelines — track hiring velocity at target companies; diff successive runs to spot new headcount or sudden freezes.
- Competitive analysis — monitor which roles a competitor is hiring for and in which locations.
- Job aggregators — power a niche job board (e.g. "remote fintech jobs") without scraping fragile HTML pages.
- Recruitment automation — feed a CRM or ATS of your own with normalised job data from multiple sources in one shot.
- Market research — identify which departments are growing fastest across an industry by counting roles by department field.
- No-code workflows (n8n / Make / Zapier) — connect via the Apify integration node; pipe new postings to a Slack channel or Google Sheet without writing code.
⚙️ How to use it
- Click Try for free at the top of the page.
- In the Companies field, enter a JSON array of
{atsType, companySlug}objects — for example:[{"atsType": "greenhouse", "companySlug": "stripe"},{"atsType": "lever", "companySlug": "vercel"},{"atsType": "ashby", "companySlug": "linear"}] - Adjust Max items per company if you want a quick sample; leave at
0for all postings. - Toggle Include description off if you only need metadata (faster, smaller dataset).
- Click Start. Results stream into the run's dataset in real time.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the Apify API.
For no-code workflows: install the Apify node for n8n or the Apify module for Make, connect your Apify token, and point it at DevilScrapes/multi-ats-jobs-scraper.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
companies | array | yes | [{"atsType":"greenhouse","companySlug":"stripe"},...] | List of {atsType, companySlug} objects. Mix platforms freely. |
maxItemsPerCompany | integer | no | 0 | Max postings per company. 0 = unlimited. |
includeDescription | boolean | no | true | Fetch and store full job description text/HTML. |
proxyConfiguration | object | no | {"useApifyProxy": true} | Apify Proxy config. We rotate sessions to absorb rate limits. |
Example input:
{"companies": [{"atsType": "greenhouse", "companySlug": "stripe"},{"atsType": "lever", "companySlug": "vercel"},{"atsType": "ashby", "companySlug": "linear"}],"maxItemsPerCompany": 50,"includeDescription": true,"proxyConfiguration": {"useApifyProxy": true}}
📤 Output
One dataset row per job posting. All fields are present on every row; optional fields are null when not available from the ATS.
| Field | Type | Notes |
|---|---|---|
source_ats | string | "greenhouse", "lever", or "ashby" |
company | string | Company slug from your input |
job_id | string | Posting ID from the ATS |
title | string | Job title |
location | string | null | Location string from the ATS |
department | string | null | Department or team |
employment_type | string | null | e.g. "Full-time", "Contract" |
remote | boolean | null | true = remote eligible; null = unknown |
url | string | Canonical link to the job posting |
posted_at | string | null | ISO-8601 creation timestamp |
updated_at | string | null | ISO-8601 last-updated timestamp |
description | string | null | Full description (null if includeDescription is false) |
Example output row:
{"source_ats": "greenhouse","company": "stripe","job_id": "4987321004","title": "Software Engineer, Payments Infrastructure","location": "San Francisco, CA","department": "Engineering","employment_type": "Full-time","remote": false,"url": "https://boards.greenhouse.io/stripe/jobs/4987321004","posted_at": "2026-05-10T14:32:00Z","updated_at": "2026-06-01T09:11:00Z","description": "<p>We're looking for an engineer to...</p>"}
💰 Pricing
This Actor uses Pay-Per-Event pricing — you pay only for job postings written to your dataset.
| Event | Price |
|---|---|
| Actor start (one-off warm-up) | $0.005 |
| Per result emitted | $0.0015 |
Effective rate: $1.50 / 1 000 results.
A run that collects 500 job postings across three companies costs approximately $0.75 in result charges plus the $0.005 start fee. Empty runs (no matching postings) cost only the start fee.
🚧 Limitations
- Company slugs must exist on the chosen ATS. Passing an incorrect slug returns zero results for that company (logged as a warning, not a fatal error).
- Ashby GraphQL schema may evolve without notice — we track public API changes but cannot guarantee instant compatibility if Ashby deprecates fields.
- Description field can contain raw HTML. Strip tags on your end if plain text is required.
- Pagination is handled automatically, but very large boards (thousands of postings) may produce long run times at the default proxy tier.
- The Actor does not support authenticated ATS boards (private job listings require employer credentials).
❓ FAQ
Can I scrape multiple companies in one run?
Yes — that's the design. The companies array can hold as many {atsType, companySlug} pairs as you need. They run sequentially; use maxItemsPerCompany to cap each one.
How do I find the correct company slug?
For Greenhouse: visit boards.greenhouse.io/<slug>. For Lever: visit jobs.lever.co/<slug>. For Ashby: visit jobs.ashbyhq.com/<slug>. The slug is the path segment in each URL.
Does this work with private / internal job boards? No. The Actor hits the same public API endpoints visible in a browser without authentication. Internal-only boards require employer credentials that this Actor does not support.
Can I schedule this to run daily? Yes. Click Schedule in the Apify Console and set a cron expression. Each run produces a fresh snapshot — diff two runs to find new or closed postings.
Can I export to Google Sheets or Airtable?
Yes, via the Apify Console integrations or the n8n / Make connectors. Point them at DevilScrapes/multi-ats-jobs-scraper and map the output fields.
🤝 Your feedback
Found a company slug that returns wrong results? Hit an ATS quirk we don't handle? Open a support ticket or leave a review on the Apify Store listing — we read every one.
Changelog
0.1 — 2026-06-07
- Initial release. Greenhouse, Lever, and Ashby scrapers via public JSON APIs. Normalised typed dataset rows with Pydantic validation.