Ats Jobs API
Pricing
from $4.99 / 1,000 results
Ats Jobs API
ATS Jobs API extracts job listings from Applicant Tracking Systems (ATS), including titles, companies, locations, descriptions, requirements, and application links. Ideal for job aggregation, recruitment, talent sourcing, market research, and hiring analytics.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Ats Jobs API — Job Titles, Salaries, Skills and Company Data
Ats Jobs API pulls job listings straight from a company's own ATS board — Greenhouse, Lever, Ashby, Workable, or SmartRecruiters — and returns them as typed, normalized JSON with titles, locations, employment type, extracted salary ranges, and required skills. No aggregator database sits in between: every listing comes from the company's own live board. Give it a company name or board URL and start the run below.
What is Ats Jobs API?
Ats Jobs API is a direct-ATS job scraper: instead of querying a jobs aggregator, it calls each supported platform's own public, unauthenticated JSON endpoint (Greenhouse, Lever, Ashby, Workable, SmartRecruiters) for the companies you name, then normalizes every result into one consistent schema. No account, login, or API key is required for any of the five platforms — their board endpoints are public by design. It's built for recruiters, sourcers, and developers who need structured job data — or AI agents that need it as clean context — without maintaining five separate API integrations themselves.
What company ATS job data is publicly available to scrape?
Every one of the five supported platforms serves its job listings through a public, unauthenticated endpoint — nothing below requires a login or an API key.
| Data Category | Publicly available | Not exposed by any supported platform |
|---|---|---|
| Job title, department, description | Yes — full HTML description included | — |
| Location (raw text + structured city/region/country) | Yes | — |
| Employment type, workplace type (remote/hybrid/on-site) | Yes, where the platform sets a structured field | Greenhouse never sets a structured employment/workplace field at all — Ats Jobs API falls back to scanning the posting text |
| Posted date, last-updated date, application deadline | Yes, where the platform tracks it | Lever, Ashby, Workable, SmartRecruiters don't expose a deadline field — only Greenhouse does |
| Skills, certifications, education requirements | Yes — extracted from the posting's own text | No platform returns these as structured fields on any list endpoint |
| Salary range | Only when the company discloses it inline in the posting text | None of the five list endpoints exposes salary as a structured field |
| Company profile (logo, LinkedIn, Crunchbase, summary) | Yes, but only what the company's own website itself publishes | No third-party company-enrichment database is queried |
| Number of applicants, internal hiring notes | — | Never exposed by any ATS platform's public API, under any circumstances |
Ats Jobs API only returns publicly visible data — the same job postings anyone can already see on the company's own careers page. Nothing behind a login wall.
What data can I extract with Ats Jobs API?
Ats Jobs API returns one JSON object per job listing, covering the posting itself, its compensation and classification signals, and the hiring company's own public profile.
Job identity and content fields
| Field Name | Description |
|---|---|
id | Deterministic UUID derived from platform + board token + the platform's own posting id — stable across runs for the same job |
title | The job title exactly as posted |
normalized_title | The title with noise stripped — trailing req IDs, "(Remote)"/"(Contract)" tags, stray commas |
description | The full job description, rendered from HTML to lightly formatted plain text |
summary | A short summary built from the posting's own intro text (falls back to the first ~200-400 characters of the description) |
listing_url | The public, human-viewable listing page |
apply_url | The direct application URL |
source | Which ATS served this job: greenhouse, lever, ashby, workable, or smartrecruiters |
locations | Array of location objects: location (raw text), city, region, country, latitude, longitude |
responsibilities | Bullet points extracted from the posting's responsibilities section (deduplicated, capped at 20) |
benefits | Bullet points extracted from the posting's benefits section (deduplicated, capped at 20) |
Compensation, classification and compliance fields
| Field Name | Description |
|---|---|
employment_type | Normalized to Full-time, Part-time, Contract, Internship, or Temporary; defaults to Full-time when the posting gives no other signal |
workplace_type | Remote, Hybrid, or On-site — from the platform's structured field, or the posting text when the platform has none |
experience_level | Entry Level, Associate, Mid Level, Senior, Staff, Principal, Lead, Director, Executive, or Internship — inferred from the platform's own seniority field, level numbers/roman numerals in the title, seniority words in the title, or years-of-experience mentions in the text |
compensation.min / compensation.max / compensation.currency / compensation.period | Salary range extracted from a $X - $Y pattern in the posting's own text, with its stated or inferred pay period; null on every field when no range is stated |
date_posted | ISO 8601 UTC — when the job was first published |
updated_at | ISO 8601 UTC — the platform's own last-updated timestamp, falling back to date_posted |
created_at | ISO 8601 UTC — when this run first saw the job (this scraper keeps no database, so this is always "now") |
valid_through | ISO 8601 UTC application deadline, from the platform's own field or a "applications close on..." pattern in the text; null if neither is present |
is_work_auth_required | true when the text explicitly requires work authorization/citizenship, null when the posting says nothing either way |
is_h1b_sponsor | true/false on an explicit sponsorship statement in the text, null when unstated |
is_clearance_required | true/false on an explicit security-clearance statement, null when unstated |
Company profile and qualifications (nested objects)
| Field Name | Description |
|---|---|
company.name | The hiring company's name |
company.website | Inferred only when the listing links to a domain that isn't the ATS itself |
company.logo_url | From the company's own site og:image/favicon tag, when company.website was resolved |
company.summary | From the company's own site meta description, when available |
company.industries | Distinct industry labels seen across the company's own board (populated only for SmartRecruiters, the one platform that exposes an industry field) |
company.linkedin_url / company.crunchbase_url | Only the company's own link to itself, scraped from its own site footer — never guessed |
company.details_url | The board's own public careers page (e.g. boards.greenhouse.io/<token>) |
company.categories | Always null — no ATS platform exposes an equivalent taxonomy |
qualifications.must_have / qualifications.preferred | Each an object with education (array of strings), certifications (array of strings), and skills (array of { "name", "type" }, type hard or soft) — matched against curated skill/certification keyword lists and degree-mention patterns run over the posting's required vs. preferred text sections |
🤖 Add-on: Need additional company or candidate data?
Once Ats Jobs API tells you which companies are hiring, ../Y-Combinator-Scraper is a natural next step for building or expanding your companies_include list from YC's startup directory. If you need to go from job listing to candidate outreach, ../LinkedIn-People-Profile-Scraper and ../Linkedin-Profile-Scraper-with-Email-&-Company-Data pull the profile and contact side of the same hiring pipeline.
Why not build this yourself?
Calling one company's Greenhouse endpoint yourself is a single GET request. The work Ats Jobs API removes is everything past that: five platforms means five different response shapes to parse (Greenhouse's jobs array, Lever's bare list, Ashby's jobs wrapper, Workable's widget payload, SmartRecruiters' paginated content plus a per-posting detail call for the actual description), each with its own location, employment-type, and date field names — or none at all. On top of that there's company resolution (a bare name has to be turned into a real board token, by guessing slugs or scanning a careers page for an embedded ATS link), a proxy escalation ladder for boards sitting behind bot protection, and re-testing all of it every time one of the five platforms changes its response shape.
Building a one-off script against a single company's board you already know is reasonable to do yourself. Reach for Ats Jobs API instead once you're tracking more than a handful of companies, don't know their board tokens up front, or need the output in one consistent schema regardless of which of the five platforms each company happens to use.
How to use Ats Jobs API
Ats Jobs API runs on the Apify platform — there's no separate signup or API key for the ATS platforms themselves.
- Open the Actor's page in the Apify Store and click Try for free (or Run, if you've already added it to your account).
- In Companies to Search, list the companies you want: a bare name (e.g.
notion), an explicitsource:token(e.g.greenhouse:stripe), or a careers-page URL. Leave it empty and the run still produces real output, using the Actor's own built-in demo list of ten public boards across all five platforms. - Optionally set Search Queries, Locations, Work Model, Employment Type, or Skills to narrow the result set — all are optional and OR'd together within each filter.
- Click Start.
- Watch results stream into the dataset live, then export as JSON, CSV, or Excel from the Output tab, or pull them via the Apify API.
How to scale to bulk job listing extraction
companies_include accepts an array, so one run resolves as many companies as you paste in — bulk input is supported natively, no loop required. concurrency (1-20, default 5) controls how many companies are resolved in parallel. There's no separate "list of URLs" input beyond this: every entry in companies_include is resolved independently and its jobs are merged into one filtered, paginated result set controlled by page and page_size.
What can you do with company ATS job listing data?
- 📊 A talent-sourcing analyst tracking hiring velocity pulls
date_postedanddepartmentacross a watchlist ofcompanies_includeto see which teams are actively growing. - 🌍 A remote-jobs newsletter curator filters on
workplace_typeandlocationsto publish only fully remote roles in specific countries. - 💰 A compensation researcher reads
compensation.min/compensation.maxalongsideexperience_levelto benchmark pay bands for a given seniority across companies on the same ATS. - 🎯 A recruiter building a sourcing shortlist matches
qualifications.must_have.skillsagainst a target skill set before reaching out. - 🤖 An AI agent builder feeds
description,qualifications, andresponsibilitiesinto a RAG index so a job-matching assistant can answer "which of these roles need Kubernetes experience" directly from typed fields instead of parsing raw HTML.
How does Ats Jobs API handle rate limits and blocking?
Every request goes through a resilient transport built on a Chrome-impersonating HTTP client, so requests carry a realistic browser fingerprint. Requests start with no proxy (fastest); on a 403 or 429 response the actor escalates automatically — no proxy → Datacenter Proxy → Residential Proxy — and once on the Residential Proxy, it stays there for the rest of the run. A blocked Residential Proxy request is retried up to 3 times on a fresh residential session before that request is given up on. A 429 response's Retry-After header is honored (capped at 30 seconds). Each request is retried up to maxRetries times (1-10, default 3) on a transient error or 5xx response, with backoff between attempts. If the network becomes completely unreachable for 12 requests in a row, the run stops and saves whatever was already collected rather than continuing to fail silently. Ats Jobs API does not solve CAPTCHAs.
⬇️ Input
All input parameters are optional — leaving everything blank runs the Actor against its own built-in demo company list.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
queries | No | Array | Job titles or keywords to filter for, OR'd together (up to 5 — extras are dropped). Prefix a term with "-" to exclude it. | ["Software Engineer", "-staff"] |
companies_include | No | Array | Companies to search: a bare name, a source:token board reference, or a careers URL. Left empty, the Actor uses its own built-in demo list. | ["greenhouse:stripe", "notion"] |
search_description | No | Boolean | Default true. When on, queries match the title and full description; when off, title only. | true |
sources | No | Array | Restrict company resolution to specific platforms: greenhouse, lever, ashby, workable, smartrecruiters. Unsupported values are dropped with a warning. | ["greenhouse", "lever"] |
locations | No | Array | Cities, regions, or countries to filter by, matched against each job's own location text. | ["United States", "Remote"] |
work_models | No | Array | Filter by workplace type: remote, hybrid, onsite. | ["remote"] |
employment_types | No | Array | Filter by employment type: full-time, part-time, contract, internship, freelance, temporary. | ["full-time"] |
experience_levels | No | Array | Filter by seniority: intern, entry, mid, senior, lead, executive. Not reliably exposed by any supported ATS list endpoint — this filter can drop nearly everything. | [] |
skills_include | No | Array | Only return jobs whose description mentions any of these skills. | ["Python"] |
skills_exclude | No | Array | Exclude jobs whose description mentions any of these skills. | ["PHP"] |
companies_exclude | No | Array | Skip these entries even if they also match companies_include. Same accepted forms. | ["greenhouse:oldco"] |
min_salary_usd | No | Integer | Minimum 0. Accepted for input compatibility only — not applied, since no supported ATS list endpoint reliably exposes a structured salary field. | 120000 |
max_salary_usd | No | Integer | Minimum 0. Same limitation as min_salary_usd. | 220000 |
posted_after | No | String | Only jobs posted on/after this date. ISO 8601 or relative (e.g. "7 days ago"). | "30 days ago" |
posted_before | No | String | Only jobs posted on/before this date. ISO 8601 or relative. | "" |
page | No | Integer | Default 1. Minimum 1, maximum 100. Which page of the filtered, combined result set to return. | 1 |
page_size | No | Integer | Default 50. Minimum 1, maximum 100. Results per page. | 50 |
include_company_details | No | Boolean | Default false. Not available in this direct-ATS Actor — no third-party enrichment source is used — accepted but ignored. | false |
concurrency | No | Integer | Default 5. Minimum 1, maximum 20. How many companies/requests to resolve in parallel. | 5 |
maxRetries | No | Integer | Default 3. Minimum 1, maximum 10. How many times to retry a single request after a transient error before giving up on it. | 3 |
proxyConfiguration | No | Object | Default { "useApifyProxy": false }. Set the RESIDENTIAL group here to start every request on a residential proxy instead of the default direct-connection-first behavior. | { "useApifyProxy": false } |
⚠️ companies_include is functionally the most important input: none of the five ATS platforms offers a global cross-company keyword search, so queries is only ever a client-side filter applied to jobs already pulled for the companies you name. Ats Jobs API cannot discover jobs at a company you didn't list.
Example input
{"queries": ["Software Engineer", "-staff"],"companies_include": ["greenhouse:stripe", "notion", "https://jobs.lever.co/leverdemo"],"search_description": true,"sources": ["greenhouse", "lever"],"locations": ["United States", "Remote"],"work_models": ["remote", "hybrid"],"employment_types": ["full-time"],"experience_levels": [],"skills_include": ["Python"],"skills_exclude": ["PHP"],"companies_exclude": ["greenhouse:oldco"],"min_salary_usd": 120000,"max_salary_usd": 220000,"posted_after": "30 days ago","posted_before": "","page": 1,"page_size": 50,"include_company_details": false,"concurrency": 5,"maxRetries": 3,"proxyConfiguration": { "useApifyProxy": false }}
⬆️ Output
Each matched job is streamed into the dataset the moment it's resolved, as one typed JSON object per job — the schema is identical no matter which of the five platforms served it. Browse it through six built-in dataset views (Overview, Company Info, Locations, Qualifications, Compensation & Compliance, All Fields) or export the full result set as JSON, CSV, or Excel. Billing is pay-per-event: every job pushed to the dataset fires exactly one row_result charged event — there are no separate uncharged rows to filter out.
Example output
{"id": "6f2a1e3b-9c4d-5e6f-8a1b-2c3d4e5f6a7b","title": "Senior Backend Engineer, Payments Infrastructure","normalized_title": "Senior Backend Engineer Payments Infrastructure","company": {"id": "3a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d","name": "Stripe","website": "https://stripe.com","logo_url": "https://stripe.com/favicon.ico","summary": "Stripe builds economic infrastructure for the internet.","industries": [],"categories": null,"linkedin_url": "https://www.linkedin.com/company/stripe","crunchbase_url": null,"details_url": "https://boards.greenhouse.io/stripe"},"description": "**Responsibilities**\n\n- Design and build resilient payment processing services\n- Partner with product teams to ship new payment methods\n\n**Requirements**\n\n- 5+ years of backend experience\n- Strong Go and SQL skills","summary": "Stripe is looking for a Senior Backend Engineer to join the Payments Infrastructure team, building the systems that move money for millions of businesses.","listing_url": "https://job-boards.greenhouse.io/stripe/jobs/5678901","apply_url": "https://job-boards.greenhouse.io/stripe/jobs/5678901","locations": [{"location": "San Francisco, CA","city": "San Francisco","region": "California","country": "United States","latitude": 37.7749,"longitude": -122.4194}],"compensation": { "min": 170000, "max": 230000, "currency": "USD", "period": "yearly" },"employment_type": "Full-time","workplace_type": "Hybrid","experience_level": "Senior","source": "greenhouse","created_at": "2026-09-03T10:15:00Z","updated_at": "2026-08-20T00:00:00Z","date_posted": "2026-08-20T00:00:00Z","valid_through": null,"qualifications": {"must_have": {"education": ["Bachelor's degree in Computer Science"],"certifications": [],"skills": [{ "name": "Go", "type": "hard" },{ "name": "SQL", "type": "hard" },{ "name": "Communication", "type": "soft" }]},"preferred": {"education": [],"certifications": ["AWS Certified Solutions Architect"],"skills": [{ "name": "Kubernetes", "type": "hard" }]}},"responsibilities": ["Design and build resilient payment processing services","Partner with product teams to ship new payment methods"],"benefits": ["Comprehensive health coverage","Equity in a private company"],"is_work_auth_required": true,"is_h1b_sponsor": null,"is_clearance_required": null}
How does it work?
For each company you name, Ats Jobs API resolves it to a real board token — either directly from an explicit source:token or careers URL, or by guessing slug variants and, for a bare URL, scanning the company's own live page for an embedded ATS link. It then calls that platform's own public JSON endpoint directly (SmartRecruiters is paginated and fetches one detail call per posting for the full description). Every request goes through a Chrome-impersonating HTTP client with automatic proxy escalation if a request gets blocked. Free-text locations are geocoded through OpenStreetMap's Nominatim service. Only publicly visible job data is ever returned, and the output schema stays identical regardless of which of the five ATS platforms — or which layout each one uses — served the job.
Integrations
Ats Jobs API runs on the Apify platform, so it's reachable anywhere an HTTP request or the Apify API client can reach it.
Calling Ats Jobs API programmatically
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("<YOUR_APIFY_USERNAME>/ats-jobs-api").call(run_input={"companies_include": ["greenhouse:stripe", "notion"],"queries": ["Software Engineer"],})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["company"]["name"])
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.
No-code tools (n8n, Make, LangChain)
In n8n, use the HTTP Request node pointed at the Actor's run-sync-get-dataset-items endpoint with your Apify API token in the Authorization header. In Make, use the built-in Apify app's "Run Actor" module the same way. In LangChain, wrap the Actor as a tool with the langchain-apify integration so an agent can call it directly and receive the dataset items as its tool output.
Is it legal to scrape company ATS job listings?
Yes — scraping publicly available job listings from a company's own careers board is generally lawful, and Ats Jobs API only ever returns data any visitor to that board can already see. This is business/job-posting data, not personal data about identifiable individuals, so the relevant framework is each platform's own terms of service rather than a personal-data regime like GDPR — no candidate names, applicant records, or other personal data are collected or returned. Consult legal counsel if your use case involves bulk storage of this data or redistribution of a company's job content.
Frequently asked questions
What job listing fields does Ats Jobs API return?
The top-level fields include title, company.name, locations, employment_type, and compensation — see What data can I extract with Ats Jobs API? for the full field-by-field breakdown across all three groups.
Does Ats Jobs API require an ATS account or login?
No. All five supported platforms — Greenhouse, Lever, Ashby, Workable, SmartRecruiters — serve their job listings through public, unauthenticated endpoints, and no Apify API key is required to click Start on the Actor's own page.
How many job listings can I extract in one run?
There's no fixed per-run cap: every company in companies_include is resolved and its jobs pulled, up to an internal scan budget of 50,000 jobs examined by the filtering pass. page_size (up to 100) controls how many of the filtered, matching jobs are returned per page, and page (up to 100) selects which page.
What happens if a company's board can't be resolved or comes back empty?
The run continues with the other companies and logs a warning naming the one that failed — nothing stops the whole run. A wrong or unrecognized entry gets reported as unmatched rather than silently returning zero jobs; for SmartRecruiters specifically, a board returning zero postings is also reported as unmatched, since that platform's API can't distinguish a genuinely empty board from an invalid token.
Can I scrape multiple companies' ATS boards at once?
Yes. companies_include accepts an array and bulk input is supported natively — paste as many companies as you want in one run, and concurrency (up to 20) controls how many are resolved in parallel.
Does Ats Jobs API work with Claude, ChatGPT, and other AI agent tools?
Yes, as an HTTP endpoint: any agent framework that can call the Apify API can start a run and read back typed JSON results, as shown in the integrations section above.
How does Ats Jobs API differ from aggregator-based job scrapers?
It queries each company's own live ATS board directly rather than a third-party jobs index, so every listing reflects that board's current state instead of a cached aggregator snapshot, and no separate aggregator API key is ever required.
Does Ats Jobs API return data in a format LLMs can use directly?
Yes. Every job comes back as typed, normalized JSON with consistent field names across runs — no HTML parsing or CSS selectors needed. Pass it straight to an LLM, index it into a vector store, or feed it to an agent tool.
What happens when an ATS platform changes its layout or response format?
Ats Jobs API is maintained, and the output schema is designed to stay stable regardless of which of the five platforms' response shapes change underneath it. No specific turnaround time is published for any given fix.
Can I use Ats Jobs API without managing proxies or browser infrastructure?
Yes. Proxy tier escalation (direct → datacenter → residential) and the Chrome-impersonating HTTP client are both handled internally — you don't configure or pay for a separate proxy pool unless you want to start on a residential proxy from the first request.
Which job listing fields work best for AI training data and RAG indexing?
For RAG, index description, summary, and responsibilities — the highest-information free text fields. For structured training data, title, company.name, employment_type, workplace_type, and source are the most consistently populated fields across every job, regardless of which ATS platform it came from; all fields return as typed primitives (strings, booleans, numbers, or arrays/objects of the same).
Related scrapers
| Scraper | What it extracts |
|---|---|
| 🌱 Greenhouse Job Scraper | Jobs from a single Greenhouse board, in more Greenhouse-specific depth |
| 💼 Naukri Job Scraper — India + Gulf · Emails & 41 Fields | India/Gulf job listings with contact emails across 41 fields |
| 🎓 Internshala Scrapper | Internship and early-career listings from Internshala |
| 🚀 Y Combinator Scraper | YC-backed startup company data — a ready-made source list for companies_include |
Your feedback
Found a bug, or a field that should be there but isn't? Let us know at dev.scraperengine@gmail.com — reports like this directly shape what gets fixed and added next.