Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby) avatar

Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby)

Pricing

Pay per event

Go to Apify Store
Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby)

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

DevilScrapes

Maintained by Community

Actor 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:

ATSAPI endpoint style
GreenhouseREST — boards-api.greenhouse.io/v1/boards/{slug}/jobs
LeverREST — api.lever.co/v0/postings/{slug}?mode=json
AshbyGraphQL — 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-After honoured.
  • 🧱 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

  1. Click Try for free at the top of the page.
  2. 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"}
    ]
  3. Adjust Max items per company if you want a quick sample; leave at 0 for all postings.
  4. Toggle Include description off if you only need metadata (faster, smaller dataset).
  5. Click Start. Results stream into the run's dataset in real time.
  6. 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

FieldTypeRequiredDefaultNotes
companiesarrayyes[{"atsType":"greenhouse","companySlug":"stripe"},...]List of {atsType, companySlug} objects. Mix platforms freely.
maxItemsPerCompanyintegerno0Max postings per company. 0 = unlimited.
includeDescriptionbooleannotrueFetch and store full job description text/HTML.
proxyConfigurationobjectno{"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.

FieldTypeNotes
source_atsstring"greenhouse", "lever", or "ashby"
companystringCompany slug from your input
job_idstringPosting ID from the ATS
titlestringJob title
locationstring | nullLocation string from the ATS
departmentstring | nullDepartment or team
employment_typestring | nulle.g. "Full-time", "Contract"
remoteboolean | nulltrue = remote eligible; null = unknown
urlstringCanonical link to the job posting
posted_atstring | nullISO-8601 creation timestamp
updated_atstring | nullISO-8601 last-updated timestamp
descriptionstring | nullFull 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.

EventPrice
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.