Greenhouse, Lever & Ashby Jobs Scraper
Pricing
from $1.00 / 1,000 job delivereds
Greenhouse, Lever & Ashby Jobs Scraper
Scrape jobs from Greenhouse, Lever and Ashby career pages. Get titles, locations, remote flags, salary where available, descriptions and apply links. Filter before billing. No ATS API key or proxy. $1 per 1,000 jobs plus the platform start charge.
Pricing
from $1.00 / 1,000 job delivereds
Rating
0.0
(0)
Developer
Heim AI
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Greenhouse, Lever & Ashby Jobs Scraper - Company Career Pages
Export public job postings from company career pages on Greenhouse, Lever and Ashby. Paste careers URLs or board tokens, get one clean JSON row per job: title, location, department, remote flag, salary when the employer publishes it, posted date, apply URL and a plain-text description. No ATS API key, ATS login or proxy required. $1 per 1,000 jobs plus $0.00005 per run. Filters and limits let you choose which jobs to receive.
| Actor id | kaz_kakyo/greenhouse-lever-ashby-jobs-scraper |
| Minimal input | { "boards": ["https://boards.greenhouse.io/airbnb"] } |
| Cost | $0.001 per job delivered (+ a nominal $0.00005 per run) |
| Output | Jobs-only default dataset; free summaries, errors and notices in a separate status dataset |
What it does
Companies that hire through Greenhouse, Lever or Ashby publish their open roles on a public careers page (boards.greenhouse.io/<company>, jobs.lever.co/<company>, jobs.ashbyhq.com/<company>). This actor reads those boards through the vendors' public job-board endpoints — the same ones the careers pages use — and normalises the postings of all three vendors into one schema. Give it the companies you care about; it returns their live jobs.
Typical uses: watch the careers pages of target accounts (hiring signals for sales and recruiting), build a niche job board from a list of companies, feed an AI agent or an n8n / Make workflow with structured postings, or export a company's whole board to a sheet.
It is not a cross-company jobs search engine. You supply the boards; it fetches them. Use (ats, region, board, jobId) to compare results across runs for "new since last time".
Input
| Field | Default | Description |
|---|---|---|
boards | (required) | Careers URLs (https://boards.greenhouse.io/<slug>, https://job-boards.greenhouse.io/<slug>, https://jobs.lever.co/<slug>, https://jobs.ashbyhq.com/<slug>, EU hosts too), vendor tokens (greenhouse/<slug>, lever/<slug>, ashby/<slug>) or a bare <slug> (all three vendors are tried). Max 200 per run |
maxJobsPerBoard | 500 | Cap per board, applied after filters (max 5000) |
descriptionFormat | text | text (plain text, compact), html (as published) or none (description is null, everything else kept) |
keyword | — | Case-insensitive substring match on the job title |
location | — | Case-insensitive substring match on location text (primary + secondary locations, country) |
remoteOnly | false | Ashby/Lever remote flags; Greenhouse title or location containing the word remote |
postedAfter | — | ISO date; keeps jobs posted on or after it (Greenhouse: first-published date when present, else last updated; postings with no date at all are excluded) |
maxTotalJobs | 5000 | Run-wide cap (max 20000) |
includeBoardSummary | true | Write one free summary per resolved board in the status dataset; errors and notices remain available when false |
Filters and caps are applied before billing — you pay only for delivered job rows.
Output
The default dataset and Jobs output contain only job rows, with all fields including applyUrl and description. The separate, run-scoped status dataset and Boards & errors output contain board summaries, errors and notices. Both output URLs are available in the run API response.
type | Charged? | Meaning |
|---|---|---|
job | Yes ($0.001) | One job posting |
board | No | Per-board status: ok, empty (the board exists but publishes nothing through its public API, or only unlisted postings), duplicate (the same board reached through two entries — delivered once), with totalJobs / filteredOut / deliveredJobs / skippedJobs counts and a note when a cap or the budget cut the board short |
error | No | A board that could not be fetched (not-found, blocked, rate-limited, upstream-error, timeout, network-error, bad-json, too-large, pagination-limit) or an invalid input entry (invalid-input) |
notice | No | Run-level events: max_total_jobs_reached, boards_capped, invalid_entries_capped, charge_limit_reached, billing_state_unknown, run_interrupted; detail carries the explanation |
Example job row (illustrative values):
{"type": "job","ats": "ashby","board": "ramp","region": "global","boardUrl": "https://jobs.ashbyhq.com/ramp","jobId": "a1b2c3d4-0000-4000-8000-000000000001","title": "Product Designer","location": "New York","secondaryLocations": ["Remote (US)"],"department": "Design","team": "Growth","employmentType": "FullTime","workplaceType": "onsite","isRemote": false,"country": "United States","salary": { "min": 150000, "max": 190000, "currency": "USD", "interval": "1 YEAR" },"salaryText": "$150K - $190K","postedAt": "2026-08-20T00:00:00.000Z","updatedAt": null,"url": "https://jobs.ashbyhq.com/ramp/a1b2c3d4-0000-4000-8000-000000000001","applyUrl": "https://jobs.ashbyhq.com/ramp/a1b2c3d4-0000-4000-8000-000000000001/application","requisitionId": null,"description": "Design great things.","descriptionTruncated": false,"fetchedAt": "2026-09-02T00:00:00.000Z"}
Field notes, by vendor:
- Greenhouse —
locationis the posting's location;secondaryLocationsare its offices;departmentis the first department.postedAtusesfirst_publishedwhen the list response includes it; otherwise it isnullandpostedAfterfalls back toupdatedAt. Structuredsalaryis returned only when the list response includes pay ranges; it is not guaranteed for every board.applyUrlis the job page. - Lever —
employmentTypeis the commitment (Full-time, Contract…),workplaceTypeisremote/hybrid/onsiteas set by the employer,salarycomes from the posting's salary range,postedAtis the posting's creation time. Use the EU careers URL for an EU board; an identical slug on global and EU hosts identifies separate boards. - Ashby —
isRemoteandemploymentTypeare the employer's flags,salaryis the published salary component (equity components are ignored),salaryTextis the employer's summary string; both arenullwhen the employer switched compensation display off. Unlisted postings are never returned.postedAtis the last publication time reported by Ashby;isRemotecan be true on a hybrid posting if the employer permits remote locations.
Salary is never parsed out of description text — it is only present when the employer published it as structured data.
Pricing
| Event | Price |
|---|---|
Job delivered (job-delivered) | $0.001 per job row |
Run start (apify-actor-start) | $0.00005 (nominal) |
Worked examples: a board with 120 open roles costs about $0.12; 50 boards averaging 40 roles cost about $2. Board, error and notice rows are free.
Cap spend with maxTotalChargeUsd on the run. When the charge budget is exhausted, delivery stops cleanly — the remaining jobs of the current board and the remaining boards are skipped, the board row says so in note, and a charge_limit_reached notice is written. If the actor cannot read its own billing state on the platform it stops instead of delivering unbilled data and writes a billing_state_unknown notice (fail-closed).
Quick start (Console)
- Open the actor in Apify Console.
- Keep the prefilled boards or paste your own careers URLs.
- Click Start. Open Jobs for postings and Boards & errors for results from each board. An empty Jobs result can mean filters matched nothing or a board failed; check the status output before deciding.
Example inputs
Export a company board: request up to 5,000 Airbnb jobs with full text descriptions. Check the board summary for any cap or error before treating the export as complete.
{"boards": ["https://boards.greenhouse.io/airbnb"],"maxJobsPerBoard": 5000,"maxTotalJobs": 5000,"descriptionFormat": "text"}
Find remote engineering roles: filter Ramp's supplied board by title and remote flag, returning at most 100 matches. This does not search other companies; "remote" may still have location restrictions.
{"boards": ["https://jobs.ashbyhq.com/ramp"],"keyword": "engineer","remoteOnly": true,"maxJobsPerBoard": 100,"maxTotalJobs": 100}
API
Apify API calls require your Apify API token; the source job boards require no separate ATS credentials.
curl -X POST \"https://api.apify.com/v2/acts/kaz_kakyo~greenhouse-lever-ashby-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"boards":["https://boards.greenhouse.io/airbnb","https://jobs.ashbyhq.com/ramp"],"keyword":"engineer","maxJobsPerBoard":100}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('kaz_kakyo/greenhouse-lever-ashby-jobs-scraper').call({ boards: ['https://jobs.ashbyhq.com/ramp'], keyword: 'engineer', remoteOnly: true, maxJobsPerBoard: 100 },{ maxTotalChargeUsd: 2 },);// Page through the jobs-only default dataset for large exports.const dataset = client.dataset(run.defaultDatasetId);for (let offset = 0; ; offset += 1000) {const { items } = await dataset.listItems({ offset, limit: 1000 });for (const job of items) console.log(job.title, job.applyUrl);if (items.length < 1000) break;}// Follow run.output.boards for board summaries, errors and notices.
MCP / agents
Callable through the Apify MCP server as a tool. Pass boards (careers URLs are fine — an agent usually already has them) and optional keyword / location / remoteOnly / maxJobsPerBoard; read the Jobs output for complete job rows and Boards & errors for per-board outcomes. Use descriptionFormat: "none" for the smallest payload (every other field, including Greenhouse departments and offices, is still delivered) and maxJobsPerBoard to bound tokens. Input that violates the schema is rejected with HTTP 400 before a run is created; input that passes the schema but is unusable produces uncharged error rows without failing the run.
Scheduling
Use Apify Schedules to re-fetch a list of boards daily or hourly, attach a webhook on SUCCEEDED, and compare (ats, region, board, jobId) against the previous run to detect changes. Only infer a closed job after a complete, successful fetch with the same filters; a cap, failed board or changed filter can also make a job disappear. Job ids are stable between fetches; Greenhouse appears to mint a new id when a role is reposted (observed, not documented).
Limits (honest)
- Only Greenhouse, Lever and Ashby boards are supported (careers URLs may be pasted with or without
https://). Workday, iCIMS, Taleo, SuccessFactors, Workable, SmartRecruiters and other ATSs are not — unsupported URLs produceinvalid-input; a missing board on a supported vendor producesnot-found. - Some companies publish zero jobs through the public API while their site shows openings (they hide roles from the API on purpose). Those boards get a
boardrow withstatus: "empty"— that is the correct reading, not a bug. - Dates can be missing. Greenhouse uses first-published time when provided, falling back to last-updated time for the
postedAfterfilter; jobs without either date are excluded by that filter. - Lever global and EU demo boards passed live verification. Broader coverage remains provisional; a later-page fetch failure produces an error row and no partial board.
- Lever boards that return 50 full pages (5,000 postings) produce an uncharged
pagination-limiterror; no potentially incomplete board is delivered. The run still succeeds. Filters and delivery caps cannot turn an incomplete fetch into a complete result. - Lever EU and global boards are separate namespaces. The
regionfield distinguishes them; compare(ats, region, board, jobId)across runs. - Fetches use a 15 s timeout, one retry on rate limits, upstream errors, timeouts and network errors, three boards in parallel with a per-host spacing. Very large boards (thousands of roles with descriptions) can take a minute or two.
- EU boards: Lever EU (
jobs.eu.lever.co) is supported; a Greenhouse EU careers URL is tried on the documented API host and then, best-effort, on an EU host — if neither answers it is reportednot-found. - Descriptions are capped at 20,000 characters (
descriptionTruncated: truewhen cut). Individual API responses above 16 MB are refused (too-large). - Max 200 boards per run, 5,000 jobs per board, 20,000 jobs per run. Default run timeout 3,600 s; 90 s before its timeout the actor stops dispatching boards, clamps in-flight fetches to the time left and stops charging, and reports what it left out in a
run_interruptednotice to leave time for a clean finish. Platform failures or delivery failures can still fail a run. - The actor extracts job postings only — no recruiter or contact fields are read from the ATS payloads; descriptions are delivered as the employer published them and may contain whatever the employer wrote. Your board entries are the only input echoed back (in
board/errorrows). Data requests go only to the supported vendors' API hosts; optional usage telemetry is described below. The careers URLs you paste are parsed for the board slug and never fetched themselves (scheme-less hosts such asjobs.lever.co/netflixare accepted).
Telemetry
When optional usage telemetry is enabled, the actor attempts a start record and a charge summary in the developer's telemetry dataset. Records contain the run ID, a salted account hash (not the raw account ID), run origin, timestamps, paying-account flag and charged-event counts. Inputs and job results are not sent. Telemetry is optional and does not affect extraction or billing.
Looking for transcripts of a company's podcasts or talks instead? See Audio Transcription and YouTube Transcripts from the same developer.