Greenhouse, Lever & Ashby Job Postings Scraper
Pricing
from $0.70 / 1,000 results
Greenhouse, Lever & Ashby Job Postings Scraper
[From $1.00/1K, no usage fees] Export open jobs from public Greenhouse, Lever and Ashby career boards into one schema: title, location, remote flag, department, seniority, tech tags and salary where the employer publishes it.
Pricing
from $0.70 / 1,000 results
Rating
0.0
(0)
Developer
Vladimir Tsaplin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Export Greenhouse, Lever and Ashby jobs from public career boards into one table, with full descriptions. Use it to see who is hiring, where and for what. Name a company, paste a board URL, or search the built-in catalogue of 8,661 boards. Sample record from a real run on 2026-10-31:
{"ats_provider": "ashby","company_name": "Ramp","title": "Machine Learning Engineer","department": "Data","location": "New York, NY (HQ)","workplace_type": "hybrid","is_remote": false,"employment_type": "Full-time","salary_min": 200000.0,"salary_max": 330000.0,"salary_currency": "USD","salary_interval": "YEAR","salary_summary": "200,000 - 330,000 USD / YEAR","salary_source": "ats_structured","tech_stack_tags": ["python","postgres","pytorch","llm","snowflake","dbt"],"published_at": "2026-09-23T19:39:11.015+00:00","job_url": "https://jobs.ashbyhq.com/ramp/2888b101-b1da-4e53-a02e-1bb9b1b5a951"}
What you get
| Field | Example | Notes |
|---|---|---|
title | Machine Learning Engineer | As published |
company_name | Ramp | From Greenhouse. Ashby and Lever do not publish it, so it comes from the board address and can differ in spelling, such as Openai |
location | New York, NY (HQ) | As published. All offices are in offices |
workplace_type | hybrid | remote, hybrid or onsite, as the ATS publishes it. Otherwise from the location text |
is_remote | false | True when the ATS or the location says remote, which includes a choice of offices or remote, as in San Francisco; Seattle; Remote. False for hybrid and on-site jobs. Null when neither the ATS nor the location says |
department | Data | As published |
employment_type | Full-time | Full-time, Part-time, Contract, Temporary or Internship, read from whole words of what the employer wrote. Ashby and Lever publish it for most jobs, Greenhouse only where the employer adds an Employment Type field. Other values, such as Regular or Per Diem, stay null, and so does a value that offers a choice, such as Full Time/Part Time. A term beats the hours, so Contract Full time is Contract |
seniority_level | null | Only when the title says it: entry, senior, lead_staff or executive. The word Staff counts only in front of a role, as in Staff Engineer, not in Staff Nurse or Member of Technical Staff. Chief of Staff and Lead Generation Specialist name no level. Otherwise null |
tech_stack_tags | python, postgres, pytorch, llm, snowflake, dbt | 24 technologies found in the title and description |
salary_summary | 200,000 - 330,000 USD / YEAR | Only where the employer publishes it. The amounts are printed as published, with cents only where they are not whole, as in 16.50 - 17.50 USD / HOUR |
salary_ranges | One entry per range | Every range the job publishes, each with its amounts, currency, interval and label |
published_at | 2026-09-23T19:39:11.015+00:00 | Publication time from Greenhouse and Ashby. Lever publishes none, so for Lever this is when the posting was created |
description | Full text | The whole job description as plain text, not a snippet. For Lever that is the text its public job page shows, with the lists, pay note and closing section. Phone numbers, email addresses that may name a person, personal profile or scheduling links and names given as someone to contact are masked. See the FAQ for what stays |
apply_url | Link | Application page |
Three ways to choose boards
- Company names. Enter names such as Stripe or Linear. The Actor reads the catalogue board with exactly that name. A few names belong to 2 or 3 boards, often of different companies, and then all of them are read. A name it does not know is tried as a board address on the systems you selected, or on all of them if you selected none, so another company with that address can answer. Turn on Also match names that start with this text to include near names: Meta then also finds Metabase.
RUN_SUMMARYlists the board each name reached. - Board URLs or slugs. Paste
https://boards.greenhouse.io/figma, or writegreenhouse:figma,ashby:linearorlever:palantir. Boards on Lever's EU instance work the same way:https://jobs.eu.lever.co/some-companyorlever_eu:some-company. Lever tells upper from lower case, so write such a board as its address does, as inlever:BeemEnergy. Ashby boards can hold spaces, as inashby:The Browser Company. - Catalogue search. Turn on Search the whole company catalogue, then add a keyword or location. It reads the largest boards first, up to Boards to read from the catalogue. See Limits for how many boards a run gets through.
The catalogue holds 8,661 boards (4,220 Greenhouse, 2,803 Ashby, 1,638 Lever) that had at least one open job on 2026-10-31. Each one was checked against the board's own API on that date, and vendor demo boards and sandbox or test instances were left out. The 100 largest are 68 Greenhouse, 20 Lever and 12 Ashby boards. It is a list of where to look: the jobs themselves are read live on every run. It holds no boards on Lever's EU instance yet, no Lever boards with capitals in their address and no Ashby boards with spaces in theirs, so give those by URL or by name. A name outside the catalogue is also tried as you typed it, so The Browser Company reaches its Ashby board.
A slug or name without a system is tried on each ATS until one answers with open jobs. An empty board on one system does not end the search, and probed_boards in RUN_SUMMARY shows which board answered and which were empty.
Salary coverage
A salary appears only when the employer publishes it, so many jobs have none. In one run on 2026-10-31 over every open job on 8 technology company boards (Figma, Stripe, Brex, Affirm, Linear, Ramp, Notion and Palantir), 2,043 jobs in all, the salary was filled for 550 of 1,394 Greenhouse jobs, 264 of 350 Ashby jobs and 193 of 299 Lever jobs. Expect it to vary by employer.
salary_source shows where a salary came from: ats_structured is the ATS pay field, description_text is a range found in the job text. A range in the text counts only when the words before it name pay, so equity grants, bonuses and phrases such as high-wage careers are left out. In job text, a range below 15,000 or stated per hour, day or week is not captured, so hourly pay such as $28 - $32 per hour stays null unless the ATS pay field holds it. A range in the text is read when a sign stands in front of it, with or without cents, as in $156,800.00 - $235,200.00/yr; when it is written between $130,000 and $155,000; or when a currency code stands right behind it and there is no sign, as in 101,000 - 151,000 CAD. Two amounts joined by and without the word between, and a pair of numbers with neither a sign nor a code, are missed. Compact and European forms such as $135-145k and 70.000 bis 80.000 EUR are also missed.
salary_basis is ote when the employer states on-target earnings, which include commission, in the pay field or in the words that qualify the range. In job text, that is the word directly behind a range, or else the nearest one in front of it. In a pay field, it is the label of that range, and an OTE word with a figure of its own outside the range is about that figure: a $150K - $200K salary with the note $300-400k OTE has a null basis. Sales jobs often give both figures, as in "base salary range $80,000 - $115,000, with a target OTE of $160,000 - $230,000": the base range then has a null basis and the OTE range has ote. salary_min, salary_max and salary_basis describe the first range the employer lists, and salary_ranges holds each range with its own basis. A null basis means no such word governs that range, not that it is proven base pay. OTE given as one amount and not as a range, such as "OTE of up to $350,000", is not captured, and neither is an OTE figure in a pay field note.
Employers type these figures by hand, so a pay field that cannot be real is dropped and the Actor then looks in the job text, leaving the salary null if there is none. That covers placeholders such as 1 - 1, a maximum over 10 times the minimum, amounts below a floor for their interval (3 per hour, 10 per day, 50 per week, 100 per month, 1,000 per year) and, in USD, EUR, GBP, CAD, AUD, CHF, SGD and NZD, amounts above a ceiling (1,000 per hour, 20,000 per day, 50,000 per week or month, 2,500,000 per year). Of 12,521 pay ranges sampled from 721 boards on 2026-10-31, this dropped 235, such as 93,600 USD per hour and 40 USD per year. Lever pay every two weeks or twice a month keeps its amounts, with salary_interval null.
salary_currency is null when a range shows only a bare $ and no currency is named next to it, because $ can also mean CAD, AUD or others. That was 603 of the 1,007 salaries in the run above, so the amount is there but the currency is yours to judge. salary_interval is null when the text does not say the range is per year or per month, either in front of it, as in annual salary range, or right behind it, as in $100,000 - $120,000 annually: the Actor does not assume it. A unit word that goes with something else stays out of it, as in $100,000 - $120,000 plus annual bonus. That was 273 of the 1,007.
Some jobs publish several ranges, one per pay zone or level: 139 jobs in the run above. salary_min, salary_max and salary_summary then show the first range the employer lists, which is often the highest zone, and salary_ranges holds all of them with their labels. Ashby jobs show the span across their tiers in the first fields and each tier in salary_ranges. For pay benchmarks, use salary_ranges.
How much does it cost to scrape Greenhouse jobs?
You pay per job in the output, with no usage fees.
| Apify plan | Price per 1,000 jobs | 10,000 jobs |
|---|---|---|
| Free | $1.00 | $10.00 |
| Starter (Bronze) | $0.90 | $9.00 |
| Scale (Silver) | $0.80 | $8.00 |
| Business (Gold) | $0.70 | $7.00 |
A run also carries Apify's small start fee of $0.00005 per run for each GB of memory. Set Maximum jobs in total to cap a run. A board that fails or has no open jobs creates no result and no charge.
How to run it
- Enter company names or board URLs, or turn on the catalogue search.
- Add a keyword, location or Remote jobs only if you want.
- Press Start and download CSV, JSON or Excel from the Output tab.
A keyword is searched as text in the title, department and team, so engineer also finds Engineering and java also finds a title such as JavaScript Engineer. A technology tag counts only as a whole value: python finds jobs tagged python, while java leaves out a job tagged only javascript and sales leaves out one tagged only salesforce. Also search full descriptions adds the job text, also searched as text.
To follow hiring over time, save the input as a task, add a schedule and compare the runs.
Limits
- Up to 5,000 jobs per board and 1,000 boards per catalogue search. The 100 largest boards hold about 88,000 jobs and the 1,000 largest about 182,000.
- How far a catalogue search gets in the default 15 minutes depends on its filters and on CPU, which follows memory on Apify: 1 GB gets a quarter of a core and 4 GB a full core. A filter rejects a job before its text is processed, so a keyword or location gets through far more boards than no filter at all. The table shows runs of the release image on 2026-10-31, on a fast machine limited to that CPU share and to half of it, because a cloud core can be slower. They ran against the live boards but not on Apify, so treat them as a guide.
| Catalogue run | CPU share of the memory | Half of that share |
|---|---|---|
| 1 GB, keyword in titles such as engineer, 25 jobs per board, 100 boards | All 100 in 5 minutes | All 100 in 6 minutes |
| 1 GB, the same over 1,000 boards | All 1,000 in 15 minutes | 512 boards finished |
| 1 GB, keyword that is a technology tag, such as python, 25 jobs per board, 100 boards | All 100 in 6 minutes | 76 boards finished |
| 1 GB, no filter, 5,000 jobs per board, 100 boards | 54 boards finished, 71,707 jobs | 4 boards finished, 17,818 jobs |
| 4 GB, no filter, 5,000 jobs per board, 100 boards | All 100, 88,489 jobs, in 4 minutes | All 100 in 7 minutes |
- A search with Also search full descriptions costs about the same as the technology tag row.
- A run that reaches its timeout keeps what it read and still succeeds.
RUN_SUMMARYand the status message say how many boards it did not read, andnot_processed_targetsnames them. Boards run largest first, so the ones left are the smaller ones. To reach them, add a filter, lower Boards to read from the catalogue, choose fewer Systems to use, raise the memory or raise the timeout. - Maximum jobs in total defaults to 1,000 and can end a run first: the keyword engineer at 25 jobs per board reached it after 74 of 100 boards. Raise it to read them all.
- Open jobs only, as they stand at the moment of the run. The Actor keeps no history of closed jobs. Ashby jobs the employer marks as unlisted are left out, because they are not on the public board.
- A board with no open jobs is reported in
RUN_SUMMARYasBOARD_EMPTY. A run in which no board had any ends as failed, not as a green run with an empty dataset. A board with open jobs of which none pass your filters is a normal result. - A job object with no id or title is left out and not charged. Employers do publish these, so one does not cost you the rest of the board:
RUN_SUMMARYcounts them injobs_skippedand per board injobs_skipped_by_board. Greenhouse and Ashby boards are counted whole. On Lever, the count covers the pages the run read. A job with a title but no text at all stays in the output with an emptydescription: 39 of 13,437 Lever jobs sampled on 2026-10-31 were published that way. - A board entry that is not a job object, or a board where no entry has an id and a title, fails that board with
UNEXPECTED_RESPONSE. That usually means the ATS changed its API, though a board whose only posting is blank fails the same way. Nothing from it is stored or charged. - Greenhouse has no employment type field of its own, so that column is filled only where the employer adds one. Most boards do not. Lever and Ashby publish it for most jobs.
- Large boards take a lot of memory, so the Actor needs at least 1 GB and reads fewer boards at once at lower memory settings. At the default 1 GB it reads two.
- Lever asks for one request per second, and the Actor keeps that pace across the whole run, so 100 Lever boards take at least 100 seconds at any memory setting. A name outside the catalogue can take a few requests on each Lever instance, one per spelling.
- The catalogue is a snapshot. A company that joined later still works by name or URL.
FAQ
How do I find a company's slug? You do not need to: enter the company name. If you want it, it is the last part of the board address, such as figma in boards.greenhouse.io/figma.
Can a description search find a masked contact? No. Also search full descriptions reads the text as it is stored, with contacts already masked, so a masked name or address finds nothing.
Is it legal to collect these jobs? The Actor reads the public job board APIs that these systems offer for publishing open positions, with no login. The job text stays the employer's content, so check your rights before you republish it.
A company is missing from the results. Why? Open RUN_SUMMARY in the run's key-value store. It lists each failed board with a code such as BOARD_NOT_FOUND or BOARD_EMPTY, and not_processed_targets names the boards a run did not finish, for example because it reached Maximum jobs in total. Many companies use another ATS, and the Actor reads only these three.
Does it collect recruiter names or contacts? There are no such fields. A description is kept as the employer published it, except for contact details: a phone number becomes [phone removed], an email address that may name a person becomes [email removed], and a LinkedIn or XING profile link or a personal scheduling link such as Calendly becomes [link removed]. A name given as someone to contact becomes [name removed]: next to a contact (contact Jane Doe at ...), in a signature above one, on a line of its own under a label such as Recruiter: or Hiring Manager:, or below a line that announces a contact person. Shared mailboxes such as careers@ and company pages stay. A company helpline is masked too, because a number alone does not say whose it is.
Can a person's name still appear in a description? Yes. Names in ordinary job text stay as published, such as "you will report to Jane Doe" or "an interview with Jane, our recruiter". So do first names next to a masked profile link when no contact word leads to them, as in a list of founders. Telling a name from other capitalized words takes more than a pattern, so masking is a best effort: a number in an unusual format or a name in an unusual layout can get through, and now and then a capitalized word next to a contact, or a long number such as a contract clause, is masked by mistake. Treat the output as public job text, not as text free of personal data, and do not use it to look up or contact people.
Call it from your own code
curl -X POST "https://api.apify.com/v2/acts/creatortsv~greenhouse-lever-ashby-ats-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"companyNames": ["Stripe", "Linear"], "keywordFilter": "engineer", "maxItemsPerCompany": 25}'
Scope
What's Included: open jobs from public Greenhouse, Lever and Ashby boards, full descriptions, location, remote flag, department, tech tags, salary where the employer publishes it, a built-in company catalogue, per-board failure report.
What's Not Included: other ATS systems, company career sites outside these three, closed jobs, job history, salary estimates, candidate data, recruiter contact fields.
Keywords: greenhouse jobs scraper, lever jobs scraper, ashby jobs scraper, ats job postings api, job board data, salary data, hiring signals, company job listings.