Greenhouse, Lever & Ashby Jobs Scraper avatar

Greenhouse, Lever & Ashby Jobs Scraper

Pricing

from $1.00 / 1,000 job delivereds

Go to Apify Store
Greenhouse, Lever & Ashby Jobs Scraper

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

Heim AI

Maintained by Community

Actor 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 idkaz_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)
OutputJobs-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

FieldDefaultDescription
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
maxJobsPerBoard500Cap per board, applied after filters (max 5000)
descriptionFormattexttext (plain text, compact), html (as published) or none (description is null, everything else kept)
keywordCase-insensitive substring match on the job title
locationCase-insensitive substring match on location text (primary + secondary locations, country)
remoteOnlyfalseAshby/Lever remote flags; Greenhouse title or location containing the word remote
postedAfterISO 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)
maxTotalJobs5000Run-wide cap (max 20000)
includeBoardSummarytrueWrite 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.

typeCharged?Meaning
jobYes ($0.001)One job posting
boardNoPer-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
errorNoA 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)
noticeNoRun-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:

  • Greenhouselocation is the posting's location; secondaryLocations are its offices; department is the first department. postedAt uses first_published when the list response includes it; otherwise it is null and postedAfter falls back to updatedAt. Structured salary is returned only when the list response includes pay ranges; it is not guaranteed for every board. applyUrl is the job page.
  • LeveremploymentType is the commitment (Full-time, Contract…), workplaceType is remote / hybrid / onsite as set by the employer, salary comes from the posting's salary range, postedAt is 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.
  • AshbyisRemote and employmentType are the employer's flags, salary is the published salary component (equity components are ignored), salaryText is the employer's summary string; both are null when the employer switched compensation display off. Unlisted postings are never returned. postedAt is the last publication time reported by Ashby; isRemote can 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

EventPrice
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)

  1. Open the actor in Apify Console.
  2. Keep the prefilled boards or paste your own careers URLs.
  3. 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 produce invalid-input; a missing board on a supported vendor produces not-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 board row with status: "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 postedAfter filter; 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-limit error; 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 region field 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 reported not-found.
  • Descriptions are capped at 20,000 characters (descriptionTruncated: true when 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_interrupted notice 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 / error rows). 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 as jobs.lever.co/netflix are 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.