ATS Jobs Scraper — Greenhouse, Lever & Ashby avatar

ATS Jobs Scraper — Greenhouse, Lever & Ashby

Pricing

from $2.00 / 1,000 results

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

ATS Jobs Scraper — Greenhouse, Lever & Ashby

Pull open job postings straight from companies' public ATS boards (Greenhouse, Lever, Ashby). Full descriptions, skills, normalized salary, cross-run dedupe and webhook delivery. No browser, no proxy.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

Mukesh Kumar

Mukesh Kumar

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

3

Monthly active users

18 days ago

Last modified

Share

ATS Jobs Scraper — Greenhouse, Lever & Ashby Job Postings API

Scrape job postings directly from company career pages powered by Greenhouse, Lever, and Ashby. Get every open role with the full job description, department, location, salary, and apply URL in clean JSON — no browser, no proxy, no CAPTCHA, no anti-bot blocking. One HTTP request per board returns every job a company is hiring for.

Reads only public, company-published Applicant Tracking System (ATS) job-board APIs. Not affiliated with Greenhouse, Lever, or Ashby.


What this actor does

Pulls open positions from companies that publish their careers page on:

  • Greenhouse (boards.greenhouse.io/{company}) — used by GitLab, Stripe, Airbnb, Figma, Anthropic, Databricks, Cloudflare, Reddit, Discord, MongoDB, Datadog, Pinterest, Lyft, Robinhood, Instacart, and 1000s more.
  • Lever (jobs.lever.co/{company}) — used by Spotify, Netflix, GoPuff, Ro, SwordHealth.
  • Ashby (jobs.ashbyhq.com/{company}) — used by Ramp, Notion, Linear, Perplexity, Cursor, Vanta, Watershed, Replit, Cohere, Sierra.

Each scraped job is normalized into a unified schema so you can mix providers in one dataset.

Why scrape ATS boards instead of Indeed / LinkedIn / Glassdoor

Job aggregators (Indeed, LinkedIn, Glassdoor, ZipRecruiter) sit behind Cloudflare, CAPTCHAs, and aggressive rate limits, making them slow and expensive to scrape. Company ATS boards expose clean public JSON APIs that return richer data with zero blocking:

This actor (ATS boards)Aggregator scrapers
SourceCompany's own job boardRe-listed by 3rd party
Data freshnessReal-time (company-published)Lagging, sometimes stale
Full job descriptionYes, full HTML + textOften truncated
Department / team / compYes, when publishedRarely
Anti-botNoneCloudflare, CAPTCHA, IP bans
Proxies neededNoYes, residential
Cost per 10k jobsPenniesDollars
ReliabilityStable public APIsFrequently broken

Use cases

  • Recruiting & talent sourcing — monitor hiring at target companies and surface new roles the moment they post.
  • Sales / lead generation — companies posting Sales, Marketing, or DevOps roles signal buying intent for your tool.
  • Investor & market intelligence — track headcount growth across a portfolio or competitive set.
  • Job aggregator websites — build a niche board (remote-only, AI startups, fintech, design, etc.) with reliable, full-fidelity data.
  • HR analytics & compensation benchmarking — collect salary ranges (where published) across hundreds of companies.
  • Slack / email alerts — get new postings pushed to a webhook the second they appear.

Features

  • 3 ATS providers, one schema — Greenhouse, Lever, Ashby normalized to the same fields.
  • Full descriptions — plain text plus optional raw HTML.
  • Filters built in — by job title, location, department, keywords, remote-only, posted-within-days.
  • Skill & seniority extractionskills[], detectedSeniority, minYearsExperience parsed from descriptions.
  • Salary normalization — annualized min/max in your target currency (USD, EUR, GBP, INR, +12 more) using built-in or custom FX rates.
  • Cross-run deduplication — emit only NEW postings since the previous run for scheduled monitoring.
  • Webhook delivery — POST results to Slack, Make, Zapier, or any custom endpoint on finish.
  • No proxy required — public APIs, no IP rotation needed.
  • Fast & cheap — single HTTP call per board returns every job with full content.

Input

Provide at least one board (tokens per provider, or full board URLs — provider auto-detected). Every other field is optional.

Minimal input

{
"greenhouseBoards": ["gitlab", "stripe"],
"leverBoards": ["spotify"],
"ashbyBoards": ["Ramp"]
}

Full input with all options

{
"greenhouseBoards": ["gitlab", "stripe", "figma"],
"leverBoards": ["spotify"],
"ashbyBoards": ["Ramp", "Notion"],
"boardUrls": [
"https://boards.greenhouse.io/anthropic",
"https://jobs.lever.co/leverdemo",
"https://jobs.ashbyhq.com/Linear"
],
"jobTitle": "software engineer",
"location": "remote",
"searchKeywords": ["python", "kubernetes"],
"departmentFilter": "Engineering",
"remoteOnly": true,
"postedWithinDays": 14,
"maxJobsPerBoard": 0,
"maxJobs": 0,
"extractSkills": true,
"normalizeSalary": true,
"targetCurrency": "USD",
"fxRatesOverride": {},
"includeDescriptionHtml": false,
"deduplicate": true,
"onlyNewSinceLastRun": false,
"dedupeStoreName": "ats-seen-jobs",
"notifyWebhookUrl": "",
"maxConcurrency": 10,
"proxyConfiguration": { "useApifyProxy": false }
}

Input fields

Boards (at least one required)

FieldTypeDefaultDescription
greenhouseBoardsstring[]["gitlab", "stripe", "figma"]Greenhouse board tokens (slug from boards.greenhouse.io/{slug}).
leverBoardsstring[]["spotify"]Lever company slugs (from jobs.lever.co/{slug}).
ashbyBoardsstring[]["Ramp", "Notion"]Ashby org slugs, case-sensitive (from jobs.ashbyhq.com/{Slug}).
boardUrlsstring[][]Any board URL; provider is auto-detected from the host.

Filters

FieldTypeDefaultDescription
jobTitlestring""Keep only jobs whose title contains this text (case-insensitive).
locationstring""Keep only jobs whose location contains this text.
searchKeywordsstring[][]Keep jobs whose title OR description contains ANY keyword.
departmentFilterstring""Keep only jobs whose department contains this text.
remoteOnlybooleanfalseKeep only roles detected as remote.
postedWithinDaysinteger0Recency filter; 0 = no limit.
maxJobsPerBoardinteger0Cap per board; 0 = no limit.
maxJobsinteger0Total cap across all boards; 0 = no limit.

Enrichment & output

FieldTypeDefaultDescription
extractSkillsbooleantrueParse description into skills[], detectedSeniority, minYearsExperience.
normalizeSalarybooleantrueAdd normalizedSalary{} with annualized min/max in target currency.
targetCurrencystring"USD"Output currency: USD, EUR, GBP, CAD, AUD, INR, SGD, ZAR, BRL, MXN, AED, JPY, CHF, SEK, PLN.
fxRatesOverrideobject{}Override built-in FX rates, e.g. {"EUR": 0.92} (units per 1 USD).
includeDescriptionHtmlbooleanfalseInclude raw HTML description alongside plain text.

Deduplication & monitoring

FieldTypeDefaultDescription
deduplicatebooleantrueDrop duplicates within the current run.
onlyNewSinceLastRunbooleanfalseCross-run dedupe — emit only postings not seen in previous runs.
dedupeStoreNamestring"ats-seen-jobs"Named key-value store for cross-run seen-job IDs.
notifyWebhookUrlstring (secret)""POST a JSON summary of this run's jobs to Slack / Make / Zapier / custom endpoint.

Performance

FieldTypeDefaultDescription
maxConcurrencyinteger10Parallel board requests (1–50).
proxyConfigurationobject{ "useApifyProxy": false }Optional proxy. Not required — these are public APIs.

Output

One record per job, normalized across providers, written to the default dataset.

Full output example

{
"source": "greenhouse",
"boardToken": "gitlab",
"company": "GitLab",
"jobId": "8503792002",
"title": "Senior Backend Engineer, Platform",
"department": "Engineering",
"team": "Platform Infrastructure",
"location": "Remote, Americas",
"isRemote": true,
"employmentType": "Full-time",
"descriptionText": "GitLab is hiring a Senior Backend Engineer to work on our platform infrastructure team. You will design and build scalable Ruby on Rails services...",
"descriptionHtml": "<p>GitLab is hiring a <strong>Senior Backend Engineer</strong>...</p>",
"salary": {
"min": 134400,
"max": 287700,
"currency": "USD",
"period": "year",
"raw": "$134,400 - $287,700 USD"
},
"normalizedSalary": {
"min": 134400,
"max": 287700,
"currency": "USD",
"period": "year"
},
"skills": ["Ruby on Rails", "PostgreSQL", "Kubernetes", "Go", "GraphQL"],
"detectedSeniority": "senior",
"minYearsExperience": 5,
"applyUrl": "https://job-boards.greenhouse.io/gitlab/jobs/8503792002",
"jobUrl": "https://job-boards.greenhouse.io/gitlab/jobs/8503792002",
"postedAt": "2026-04-30T22:34:50.000Z",
"updatedAt": "2026-05-15T10:12:00.000Z",
"scrapedAt": "2026-05-21T10:00:00.000Z"
}

Output fields

FieldTypeDescription
source"greenhouse" | "lever" | "ashby"Which ATS provider the job was scraped from.
boardTokenstringProvider slug used to fetch the board.
companystringHuman-readable company name.
jobIdstringProvider's stable job identifier.
titlestringJob title.
departmentstring | nullDepartment name (e.g. Engineering, Sales).
teamstring | nullSub-team within department.
locationstringLocation string as published.
isRemotebooleanHeuristic remote detection from location & description.
employmentTypestring | nullE.g. Full-time, Part-time, Contract, Internship.
descriptionTextstringFull job description as plain text.
descriptionHtmlstring | nullRaw HTML description (only when includeDescriptionHtml: true).
salaryobject | nullSalary as published: min, max, currency, period, raw.
normalizedSalaryobject | nullAnnualized salary converted to targetCurrency.
skillsstring[]Extracted skills (only when extractSkills: true).
detectedSeniority"intern" | "junior" | "mid" | "senior" | "staff" | "principal" | "lead" | nullDetected from title + description.
minYearsExperienceinteger | nullMinimum years extracted from description.
applyUrlstringDirect URL to apply.
jobUrlstringCanonical job posting URL.
postedAtstring (ISO 8601) | nullFirst-published timestamp.
updatedAtstring (ISO 8601) | nullLast-updated timestamp (when provided).
scrapedAtstring (ISO 8601)When this actor fetched the job.

Export formats

The Apify dataset is available as JSON, CSV, Excel, XML, JSONL, RSS, or HTML via the dataset API, or piped directly into Google Sheets, S3, BigQuery, Airtable, or any webhook.


All slugs below were verified live to return jobs. Drop them into the matching input field.

Greenhouse (greenhouseBoards)

gitlab · stripe · airbnb · dropbox · databricks · robinhood · instacart · reddit · figma · asana · discord · gusto · samsara · cloudflare · twitch · lyft · pinterest · datadog · mongodb · elastic · peloton · sofi · affirm · chime · betterment · flexport · amplitude · airtable · calendly · faire · scaleai · anthropic

Ashby (ashbyBoards, case-sensitive)

Ramp · Vanta · Linear · Watershed · Replit · Modal · Baseten · Browserbase · Notion · Perplexity · Cohere · Zip · Sierra · Decagon · Cursor

Lever (leverBoards)

spotify · gopuff · ro · swordhealth

Companies migrate between ATS providers over time. If a slug returns nothing, check the company's current careers page URL (boards.greenhouse.io/…, jobs.lever.co/…, jobs.ashbyhq.com/…) and use the new slug.


How it works

Each provider exposes a public, unauthenticated JSON endpoint returning all open postings with full content in a single request — no pagination, no detail-page fetch, no JavaScript rendering:

  • Greenhouse: https://boards-api.greenhouse.io/v1/boards/{token}/jobs?content=true
  • Lever: https://api.lever.co/v0/postings/{company}?mode=json
  • Ashby: https://api.ashbyhq.com/posting-api/job-board/{org}?includeCompensation=true

Built on Crawlee's HttpCrawler (no browser, no Playwright). Skill extraction, salary normalization, deduplication, and webhook delivery are shared modules applied uniformly to every provider's output.

Scheduled monitoring — only NEW jobs

  1. Set onlyNewSinceLastRun: true
  2. Set dedupeStoreName: "my-target-companies" (any unique name)
  3. Optionally set notifyWebhookUrl to a Slack / Make / Zapier webhook
  4. Schedule the actor (every 30 min, hourly, daily — your call)

Each run persists seen jobIds to the named key-value store and emits only postings unseen in prior runs. Combined with the webhook, this gives you real-time new-role alerts for any list of companies.


Pricing

  • Pay-per-result: see the Apify Store page for current price per 1,000 jobs.
  • Compute: extremely low — one HTTP call per board, no browser, no proxy. Hundreds of boards scrape in under a minute.

Local development

git clone <repo>
cd ats-jobs-scraper
npm install
# edit storage/key_value_stores/default/INPUT.json
npm start

Requires Node.js 20+.


FAQ

Is scraping Greenhouse, Lever, and Ashby job boards legal? This actor only fetches publicly accessible, company-published job-board APIs — the same endpoints the companies' own careers pages call from the browser. No login, no rate-limit evasion, no anti-bot bypass. You should still consult your own legal counsel for your specific use case and jurisdiction.

Do I need a proxy to scrape these ATS boards? No. These are public, unauthenticated APIs designed to be hit from the browser. Apify Proxy is available as an option for very large board lists, but it's off by default.

How fast is it? One HTTP request per board returns every job with the full description. A list of 100 boards typically completes in under a minute on the default concurrency of 10.

How do I find a company's board slug? Open their careers page. If the URL is boards.greenhouse.io/acme → Greenhouse slug is acme. If jobs.lever.co/acme → Lever slug is acme. If jobs.ashbyhq.com/Acme → Ashby slug is Acme (case-sensitive). You can also just paste the full URL into boardUrls and the provider is auto-detected.

Can I scrape Workday, Greenhouse-embedded iframes, or Indeed? This actor covers Greenhouse, Lever, and Ashby — the three providers with the cleanest public JSON APIs. Workday, SmartRecruiters, BambooHR, and aggregators like Indeed require different scraping strategies and are outside this actor's scope.

Does it return salary? Yes, when the company publishes it in the posting (now mandatory in jurisdictions like NYC, California, Colorado, Washington, and many EU countries). Both raw salary and annualized normalizedSalary in your target currency are returned.

Can I get only new jobs since last run? Yes — set onlyNewSinceLastRun: true plus a dedupeStoreName. Ideal for scheduled monitoring with Slack / Zapier / webhook delivery.

Does it support full-text search across all companies? There is no cross-company search API on Greenhouse / Lever / Ashby — each board is fetched independently. Use jobTitle, location, searchKeywords, and departmentFilter to filter results from the boards you select.

Which fields work with which providers? All listed output fields are populated when the provider publishes them. Coverage of department, team, salary, employmentType, and updatedAt varies by provider and by company configuration; the normalized schema always has the field (with null when absent) so downstream code is consistent.

What happens if a board returns nothing? The most common cause is that the company migrated to a different ATS. Check their live careers page URL and update the slug. Failed boards never abort the run — other boards continue.


  • Greenhouse Jobs Scraper
  • Lever Jobs Scraper
  • Ashby Jobs Scraper
  • LinkedIn Jobs Scraper
  • Indeed Jobs Scraper
  • Glassdoor Jobs Scraper

Keywords

job postings scraper, ATS scraper, Greenhouse API scraper, Lever API scraper, Ashby API scraper, careers page scraper, hiring data, recruiting data, applicant tracking system, remote jobs scraper, tech jobs scraper, salary data scraper, job board API, jobs JSON API, company hiring monitor, new job alerts, jobs webhook, Slack jobs notifier