Multi-ATS Jobs Scraper - Greenhouse, Lever & Ashby
Pricing
from $2.85 / 1,000 jobs
Multi-ATS Jobs Scraper - Greenhouse, Lever & Ashby
Scrape every open job on Greenhouse, Lever and Ashby boards. The three systems name their fields differently, so the rows come back in one schema: title, location, department, type, posted date, the full description and the apply link. Filter by place or remote. $3.00 per 1,000 jobs.
Pricing
from $2.85 / 1,000 jobs
Rating
5.0
(1)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Scrape every open job on a Greenhouse, Lever or Ashby board, in one schema with the full description: 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 notes under the example row say which.
| Input | Board slugs as ats:token, for example greenhouse:stripe |
| Output | One row per open posting: title, location, department, type, posted date, apply link, full description, salary where published |
| Ceiling | Every open posting on each board, or your own per-company cap |
| Account needed | None, and no API key for any of the three |
| Price | $3.00 per 1,000 jobs on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 1,600 |
🔍 What Multi-ATS Jobs Scraper does
It reads a company's whole board from Greenhouse, Lever or Ashby, 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.
📋 What data you get from each board's jobs
| What you get | Field |
|---|---|
| Which system and which board the row came from | ats, company |
| Title, location and department | title, location, department |
| Employment type, where the system has one | employmentType |
| The company's own job page, where an applicant lands | url |
| When it was posted or last edited | postedAt |
| The whole posting as plain text | description |
| The pay, where the system publishes it | salary |
| Every place the job lists, on a location-filtered run | locations |
| The remote mark, on a remote-only run | remote |
| A real row or a diagnostic | ok |
▶️ How to scrape Greenhouse, Lever and Ashby boards
- Open Multi-ATS Jobs Scraper and click Try for free.
- Open a company's careers page and copy the slug out of its URL.
- Add one line per board to Companies (ats:token), like
greenhouse:airbnb. - Leave Max jobs per company at
0for the whole board, then click Start. - Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost to scrape Greenhouse, Lever and Ashby boards?
$3.00 per 1,000 jobs, which is $0.003 each on the Free plan. Paid plans pay a little less: $2.95 on Starter, $2.90 on Scale and $2.85 on Business. On the free plan, the $5 Apify gives you each month covers about 1,600 jobs.
You pay per posting delivered. Duplicate postings reachable from two boards are charged once, jobs
your locations or remoteOnly filter leaves out are not charged, diagnostic rows are not charged,
and if every board comes back empty, no rows are charged. If you set a maximum cost for the run, it
stops when that is reached.
📥 What you give it
{"companies": ["greenhouse:stripe", "lever:spotify", "ashby:ramp"],"maxItems": 0}
| Field | Default | What it is |
|---|---|---|
companies | box starts at greenhouse:stripe, lever:spotify, ashby:ramp | The list of boards, each written ats:token. The ats part is greenhouse, lever or ashby. |
ats | empty | For a single board instead of a list. Pick one system here and pair it with company below. Ignored when companies is filled. |
company | none | One board slug, used with ats. Ignored when companies is filled. |
leverLocations | none | Lever 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. |
locations | none | Every board. Only jobs posted in one of these places, matched as whole words in any case against every place a job lists: London finds "London, UK", New York finds "New York, NY". Up to 50. |
remoteOnly | false | Every board. Only jobs the board calls remote: Lever's and Ashby's own workplace type, where hybrid does not count, and on Greenhouse, which has no such field, the word "remote" in the job's location. |
maxItems | 0 | Cap per company, not per run. 0 means every open posting on each board. |
notionConnector | none | Optional. Write every job into your own Notion as well as the dataset. Authorise the connector once in Settings, then pick it here. |
notionParentId | none | Optional. The Notion data source ID to write into. Leave blank and the pages are created privately in your workspace. |
proxyConfiguration | off | Optional, 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.
locations and remoteOnly work on the whole board each system sends, so they cost no extra
reading, and jobs they leave out are never charged. A strict filter can return fewer jobs than
maxItems, or none, in which case the board gets a free NO_RESULTS row saying so.
📤 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}
| Field | How to read it |
|---|---|
description | The whole posting as plain text, markup stripped. Long, and the reason rows are big. |
url | The company's own hosted job page, which is where an applicant lands. |
postedAt | An 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. |
salary | Free 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. |
employmentType | Lever's commitment field or Ashby's employment type. Always null on Greenhouse. |
department | Greenhouse joins multiple departments with a comma. Lever and Ashby give department and team joined with a slash. |
locations | Only on rows of a leverLocations or locations 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. |
remote | Only on rows of a remoteOnly run, and always true there. |
🧾 Reading the output
| Row | How to spot it | Charged |
|---|---|---|
| A job | ok: true and a url | yes |
| A diagnostic | ok: false and an errorCode | no |
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.
| Code | What it means |
|---|---|
BAD_INPUT | The list was empty, an entry was not a valid ats:token, leverLocations was set on a list with Greenhouse or Ashby boards, or a locations entry had no letters in it. Nothing was read. |
NOT_FOUND | That token is not a board slug on that system. The row carries a hint showing where to copy the slug from. |
NO_RESULTS | The board exists and currently has no open postings, or none at the places or with the remote setting you asked for. The note says which. |
RATE_LIMITED | The board asked for a slower pace. |
SERVER_ERROR | The board answered with a server error. Usually passes on its own. |
NOT_SERVED | This job was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED. |
NETWORK | The board could not be reached, or answered with something that could not be read. |
TIME_LIMIT | The run got close to its time limit and stopped on its own. The jobs delivered before that are complete and charged, and boardsNotRead lists any board it did not get to. Give the run more time, or list fewer boards, to get the rest. |
A run that ends on one of these rows still finishes as succeeded, except one: when the time limit
stopped the run before any job came back, it ends as failed, with a TIME_LIMIT row saying so.
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.
💡 What people use it for
- Watching a list of competitors' boards on a schedule and spotting the day a new team opens;
urlis a stable key for telling which postings are new. - 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
departmentand the row count per company.
🚧 What it does not do
- No keyword search. You name boards, not roles. Filter the rows afterwards.
- Remote on Greenhouse is read from the location text. Greenhouse has no remote field, so a
remote job whose location never says "remote" is missed by
remoteOnly. - 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.
- It is not an official Greenhouse tool. Dami's Studio is independent and is not affiliated with or endorsed by Greenhouse, Lever or Ashby, or by any other company named on this page.
🧭 Which job scraper do you need?
| If you want | Use |
|---|---|
| Whole Greenhouse, Lever or Ashby boards, with the full description on every row | This one |
| Open jobs at companies you name, read from their own hiring system | Career Site Jobs Scraper |
| Public LinkedIn jobs by keyword and location | LinkedIn Jobs Scraper |
| Startup jobs with salary and equity | Wellfound Jobs Scraper |
| US and Canada tech jobs, with skills, seniority and the exact posted time | Built In Jobs Scraper |
| Remote jobs, with the region the employer hires from | Remotive 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.
What if I only have the company's name?
Use Career Site Jobs Scraper instead. It works out the system and the token from a name or a domain, across ten systems.
Can I call it from code or connect it to an AI assistant?
Yes. The API tab has ready-made
code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect
https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/multi-ats-jobs-scraper. Either way the
run happens on your Apify account at the same price.
Is scraping Greenhouse, Lever and Ashby boards legal?
These are the open roles companies publish on their own job boards. Postings can still carry personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping 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.