Multi-ATS Jobs Scraper - Greenhouse, Lever & Ashby avatar

Multi-ATS Jobs Scraper - Greenhouse, Lever & Ashby

Pricing

$3.00 / 1,000 job returneds

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

Multi-ATS Jobs Scraper - Greenhouse, Lever & Ashby

Scrape open jobs from Greenhouse, Lever and Ashby boards. All three publish a company's whole board as open JSON. They agree on almost no field names, so this puts them in one schema. You get the title, location, department, type, posted date, full description and apply link. $3.00 per 1,000 jobs.

Pricing

$3.00 / 1,000 job returneds

Rating

5.0

(1)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

0

Monthly active users

13 hours ago

Last modified

Share

Multi-ATS Jobs Scraper: every open role on a Greenhouse, Lever or Ashby board, in one schema

Give it a list of company board slugs and it returns every open posting on each one, with the full description text, the department, the apply link and the posting date. No keyword search, no login, no API key.

The three systems agree on almost no field names, so the rows are normalised into one shape. That also means some fields are simply absent on one system and present on another, and the table below says which.

InputBoard slugs as ats:token, for example greenhouse:stripe
OutputOne row per open posting
CeilingEvery open posting on each board, or your own per-company cap
Account neededNone, and no API key for any of the three
Price$3.00 per 1,000 jobs, flat on every plan

๐Ÿ—‚๏ธ What Multi-ATS Jobs Scraper does

Greenhouse, Lever and Ashby each publish a company's whole careers board as open JSON. This reads those feeds directly, so what you get is the company's own posting data rather than a scrape of a rendered careers page.

You name the boards as ats:token. The token is the slug in the company's careers URL: job-boards.greenhouse.io/<slug> (the older boards.greenhouse.io/<slug> works too), jobs.lever.co/<slug> or jobs.ashbyhq.com/<slug>. Several boards run a few at a time, and the same posting reachable from two boards is delivered once.

Every row carries the full description as plain text, not a snippet. That is the part most job feeds make you fetch one page at a time.

๐Ÿ“ฅ What you give it

{
"companies": ["greenhouse:stripe", "lever:spotify", "ashby:ramp"],
"maxItems": 0
}
FieldDefaultWhat it is
companiesbox starts at greenhouse:stripe, lever:spotify, ashby:rampThe list of boards, each written ats:token. The ats part is greenhouse, lever or ashby.
atsemptyFor a single board instead of a list. Pick one system here and pair it with company below. Ignored when companies is filled.
companynoneOne board slug, used with ats. Ignored when companies is filled.
leverLocationsnoneLever boards only. Only jobs posted in these places, filtered by Lever itself. Type each place exactly as the board labels it on jobs.lever.co, for example New York, NY; a label the board does not use returns no jobs. A run with this set must list Lever boards only.
maxItems0Cap per company, not per run. 0 means every open posting on each board.
notionConnectornoneOptional. Write every job into your own Notion as well as the dataset. Authorise the connector once in Settings, then pick it here.
notionParentIdnoneOptional. The Notion data source ID to write into. Leave blank and the pages are created privately in your workspace.
proxyConfigurationoffOptional, and off by default because a normal run does not need it.

One malformed entry stops the whole run. A spec that is not ats:token, or names a system other than the three, ends the run with a single BAD_INPUT row before any board is read. Check the list before a large run.

๐Ÿ“ค What you get back

A real row from a recent run, with the description cut short:

{
"ok": true,
"ats": "greenhouse",
"company": "stripe",
"title": "Abuse Investigator",
"location": "Dublin",
"department": "8611 Security Analytics",
"employmentType": null,
"url": "https://stripe.com/jobs/search?gh_jid=8172487",
"postedAt": "2026-09-12T13:25:25-04:00",
"description": "Who we are\n\nAbout Stripe\n\nStripe is a financial infrastructure platform for businesses...",
"salary": null
}
FieldWhat it is
descriptionThe whole posting as plain text, markup stripped. Long, and the reason rows are big.
urlThe company's own hosted job page, which is where an applicant lands.
postedAtAn ISO timestamp. On Lever it is when the posting was created, on Ashby when it was published. On Greenhouse it is the last time the posting was edited, because that is the date the board publishes first.
salaryFree text where the system has it. Lever gives its salary blurb, Ashby its compensation summary. Greenhouse never exposes one, so this is null on every Greenhouse row.
employmentTypeLever's commitment field or Ashby's employment type. Always null on Greenhouse.
departmentGreenhouse joins multiple departments with a comma. Lever and Ashby give department and team joined with a slash.
ats, companyWhich system and which board slug this row came from, so a multi-board run stays sortable.
locationsOnly on Lever rows from a leverLocations run: every place the job is posted. A job can match on one that is not its main city, which is the one location shows.

๐Ÿงพ Reading the output

Two kinds of row can land in your dataset.

RowHow to spot itCharged
A jobok: true and a urlyes
A diagnosticok: false and an errorCodeno

Each board reports for itself, so a run over ten boards can deliver jobs for nine and one diagnostic row for the tenth. A diagnostic row is never charged.

CodeWhat it means
BAD_INPUTThe list was empty, an entry was not a valid ats:token, or leverLocations was set on a list with Greenhouse or Ashby boards. Nothing was read.
NOT_FOUNDThat token is not a board slug on that system. The row carries a hint showing where to copy the slug from.
NO_RESULTSThe board exists and currently has no open postings, or none at the leverLocations you gave.
RATE_LIMITEDThe board asked for a slower pace. Re-run with fewer boards.
SERVER_ERRORThe board answered with a server error. Usually passes on its own.
BLOCKEDThe board would not serve the feed this time.
NETWORKThe board could not be reached, or answered with something that was not JSON.

A wrong slug is by far the commonest problem, and it shows up as NOT_FOUND. The default table view does not show errorCode, so switch the dataset to All fields when a board comes back empty.

โ–ถ๏ธ How to run it

  1. Open Multi-ATS Jobs Scraper and click Try for free.
  2. Open a company's careers page and copy the slug out of its URL.
  3. Add one line per board to Companies (ats:token), like greenhouse:airbnb.
  4. Leave Max jobs per company at 0 for the whole board, then click Start.
  5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

๐Ÿ’ฐ How much does it cost?

$3.00 per 1,000 jobs, which is $0.003 each. Flat on every Apify plan, no volume tiers.

You pay per posting delivered. Duplicate postings reachable from two boards are charged once, diagnostic rows are not charged, and if every board comes back empty, no rows are charged.

๐Ÿ’ก What people use it for

  • Watching a list of competitors' boards on a schedule and spotting the day a new team opens.
  • Building a startup jobs feed without writing three different clients for three different systems.
  • Pulling full descriptions for keyword analysis, which needs the whole text rather than a snippet.
  • Checking headcount direction by department, using department and the row count per company.

๐Ÿšง What it does not do

  • No keyword search. You name boards, not roles. Filter the rows afterwards.
  • No location or remote filter on Greenhouse or Ashby boards. They send the whole board. Lever's own location filter is the only one.
  • Only three systems. Greenhouse, Lever and Ashby. A company on anything else will not resolve.
  • You have to know the slug. There is no company-name lookup; copy it from the careers URL.
  • Greenhouse has no salary and no employment type, and its date is the last edit rather than the original posting date. That is what the board publishes.
  • Open postings only. Nothing closed, filled or draft, and no history of what used to be there.
  • Many large boards at once is the risky run. Rows are held together before they are written, so a long list of very large companies is the case most likely to run out of room. Split it.
  • No applicant-side anything. No salary benchmarks, no company profile, no reviews.

๐Ÿงญ Which jobs scraper do you need?

If you wantUse
Whole company boards on Greenhouse, Lever or AshbyThis one
Career pages on other hiring systems, by company URLCareer Site Jobs Scraper
A keyword search across one country's listingsIndeed Jobs Scraper
Startup roles with equity rangesWellfound Jobs Scraper
Tech company listings by stack and perksBuiltIn Jobs Scraper

โ“ Questions people ask

Where do I find the board token? In the careers URL. job-boards.greenhouse.io/stripe gives greenhouse:stripe, jobs.lever.co/spotify gives lever:spotify, jobs.ashbyhq.com/ramp gives ashby:ramp.

Does maxItems cap the run or each company? Each company. Five boards with maxItems at 20 is up to 100 rows.

Why is salary empty on so many rows? Greenhouse does not publish one at all. Lever and Ashby do when the company filled it in, which many do not.

How many boards can I put in one run? There is no fixed cap, but keep an eye on the size of the companies. A dozen mid-sized boards is comfortable; a dozen of the largest is not.

Can I schedule it? Yes. Daily on a fixed list works well, and url is a stable key for spotting which postings are new.

Is this legal? These are public job feeds the companies publish themselves. Postings can still carry personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.

๐Ÿ†˜ If something breaks

Open the Issues tab on the actor page. Send the run ID and the exact ats:token line that went wrong. The errorCode and hint on the diagnostic row usually name the problem on their own.