Greenhouse, Lever & Ashby Job Scraper API | $1.50/1K
Pricing
from $1.45 / 1,000 job results
Greenhouse, Lever & Ashby Job Scraper API | $1.50/1K
Scrape public Greenhouse, Lever, and Ashby jobs into structured records with titles, locations, salary, and application links. Run with company slugs or preset lists; no buyer login or API key. Pricing: $0.0015 per returned job on Free.
Pricing
from $1.45 / 1,000 job results
Rating
0.0
(0)
Developer
Vitalii Bondarev
Maintained by CommunityActor stats
0
Bookmarked
581
Total users
80
Monthly active users
10 hours ago
Last modified
Categories
Features
Share
ATS Job Scraper API
Scrape public job postings from Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters, and Personio into normalized job rows or hiring-signal reports. The Actor reads public JSON/XML endpoints and needs no buyer login or API key.
- Normalize postings into consistent rows for job boards, aggregators, and AI pipelines.
- Extract titles, locations, descriptions, salary, seniority, remote type, and application links.
- Track newly discovered and closed jobs for recurring hiring-signal feeds.
- Generate reports with hiring intensity, role families, departments, regions, and outreach suggestions.
- Start with company slugs, preset lists, or ATS auto-detection.
What you get
Fields are null when the source does not provide them; fields absent for a profile or record type are omitted.
| Field family | Fields | Type | What it contains |
|---|---|---|---|
| Job identity | ats, company | string | Hosting ATS and company slug; always set. |
| Job identifiers | job_id, global_id | string or null | Native ID and {ats}:{company}:{job_id}; both are null without a source job ID. |
| Job details | title, location, department | string or null | Posting title, location, and department. |
| Work arrangement | remote, remote_type | boolean; string or null | Remote flag and remote, hybrid, or onsite; Ashby remote can be null without a signal. |
| Team and employment | team, employment_type | string or null | Team and employment type. Only Lever, Ashby, and Personio fill team; employment_type is null for Greenhouse. |
| Seniority and pay | seniority, salary | string or null | Seniority and published salary. Seniority values are executive, vp, director, manager, principal, staff, lead, senior, intern, entry, or mid. Only Ashby and Recruitee set salary. |
| Links and posting date | url, apply_url, posted_at | string or null | Job, application, and posting-date values. Greenhouse uses updated_at, falling back to first_published; Lever epoch milliseconds become ISO 8601. |
| Run timestamp | scraped_at | ISO 8601 string | One scrape timestamp per run; absent from minimal. |
| Descriptions | description_text, description_html | string or null | Plain text and HTML when descriptions are enabled and available. compact removes HTML; minimal has neither field. |
| Change flags | is_new, is_closed | boolean | is_new appears only on new-job rows in a delta run; is_closed is true only on closed-job notices. |
| Record status | record_type, charged | string; boolean | job, closed_job_notice, or hiring_signal_report. Job rows have charged: true; closed notices have false; reports omit it. |
| Quality signal | parse_confidence | number | Share of six non-empty fields—title, company, location, url, posted_at, description_text—rounded to two decimals from 0.0 to 1.0. With descriptions off, the maximum is 0.83. |
| Report timestamp | report_generated_at | ISO 8601 string | Report generation time. Reports also share company, ats, and record_type. |
| Report metrics | total_open_roles, hiring_score, hiring_label, remote_share | integer; integer; string; number | Open-role count; score 0–100; aggressive_hiring, active_hiring, steady_hiring, low_hiring, or no_signal; and remote share 0.0–1.0, rounded to three decimals and 0.0 with no rows. |
| Hiring movement | hiring_velocity, expansion_signals | object | Velocity has recent_window_days, net_open_roles_change, and had_previous_run. Expansion has new departments, regions, role families, net change, and is_expanding. |
| Hiring breakdowns | priority_roles, department_signals, region_signals, seniority_mix, keyword_hits | array of objects; object | Role, department, and region names with counts; priority roles also have role_family, open_roles, and example_titles. seniority_mix counts junior, mid, senior, and leadership; keyword_hits maps terms to counts or {}. |
| Outreach output | recommended_outreach | array of strings | Outreach angles based on hiring trends. |
Raw output supports full, compact, and minimal. minimal retains ats, company, title, location, remote, remote_type, seniority, url, posted_at, global_id, and parse_confidence; it has no job_id, scraped_at, or description fields.
Sample output
This shortened sample omits the nonessential description_text and description_html fields. Every shown value is copied from one real dataset record.
{"ats": "ashby", "company": "openai", "title": "Research Engineer", "location": "San Francisco","remote": null, "remote_type": null, "department": "Research", "team": "Research","employment_type": "FullTime", "seniority": "mid", "salary": "$250K - $445K","url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b","apply_url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b/application","posted_at": "2025-04-05T00:03:20.653+00:00","job_id": "240d459b-696d-43eb-8497-fab3e56ecd9b","global_id": "ashby:openai:240d459b-696d-43eb-8497-fab3e56ecd9b","parse_confidence": 1, "scraped_at": "2026-11-06T16:04:25.025096+00:00","record_type": "job", "charged": true}
Pricing
The Actor uses pay-per-event pricing. job-result is one returned job posting. apify-actor-start is charged when the Actor starts; one event is charged per GB of run memory, with a minimum of one event.
| Event | Plan | Price per event |
|---|---|---|
job-result | Free | $0.0015 per event on Free |
job-result | Bronze | $0.001485 per event on Bronze |
job-result | Silver | $0.00147 per event on Silver |
job-result | Gold | $0.001455 per event on Gold |
job-result | Platinum | $0.00144 per event on Platinum |
job-result | Diamond | $0.001425 per event on Diamond |
apify-actor-start | Free | $0.00005 per event on Free |
apify-actor-start | Bronze | $0.0000495 per event on Bronze |
apify-actor-start | Silver | $0.000049 per event on Silver |
apify-actor-start | Gold | $0.0000485 per event on Gold |
apify-actor-start | Platinum | $0.000048 per event on Platinum |
apify-actor-start | Diamond | $0.0000475 per event on Diamond |
For 1,000 job-result events and one apify-actor-start event, the total is $1.50005 on Free; for 10,000 job-result events and one apify-actor-start event, the total is $15.00005 on Free. The Apify Free plan's $5 monthly platform usage credit covers 3,333 job-result events plus one apify-actor-start event at Free prices.
The Free plan caps raw output at 10 job rows per run; paid plans lift this cap. Report mode searches only the first target and returns at most one report on Free. Closed-job notices do not count toward the raw-output cap.
You pay only the events listed above. This Actor does not use Pay per event + usage, so compute, proxy traffic, and storage are not billed separately. Report mode returns hiring-signal reports and does not charge job-result events.
How to use
- Choose companies with a slug and optional ATS, or select
top-tech,ai-ml,devtools, orfintech. - Omit
atsto probe the supported ATS platforms and auto-detect the board. - Set
titleKeyword,locationKeyword, orremoteOnly, then choose descriptions and an output profile. - Enable
onlyNewSinceLastRunfor recurring feeds, orreportModefor one report per successfully fetched company. - Start the run and inspect job rows, reports,
failedTargets, and theOUTPUTsummary. - Repeat the run through Apify Schedules; daily is a starting point for recurring job-listing and hiring-signal collection.
{"companies": [{"ats": "greenhouse", "company": "stripe"}],"titleKeyword": "engineer","includeDescriptions": true,"outputProfile": "compact","maxJobsPerCompany": 50,"onlyNewSinceLastRun": false}
Export the dataset as JSON or CSV, or read it through the Apify dataset API.
Input parameters
| Parameter | What it does | Default |
|---|---|---|
companies | Company references with an ATS enum and slug; omit ats for auto-detection. | Empty |
presetLists | Selects top-tech, ai-ml, devtools, or fintech. | Empty |
titleKeyword | Keeps titles containing a case-insensitive substring. | Empty |
locationKeyword | Keeps locations containing a case-insensitive substring. | Empty |
remoteOnly | Keeps postings detected as fully remote. | false |
maxJobsPerCompany | Caps pushed raw rows after filtering; 0 means no per-company cap within other limits. | 50 |
includeDescriptions | Includes plain-text and HTML descriptions; SmartRecruiters adds one detail request per job. | true |
onlyNewSinceLastRun | Persists seen jobs and emits new jobs plus closed notices on later runs. | false |
outputProfile | Selects full, compact, or minimal raw output. | full |
reportMode | Replaces raw rows with one hiring-signal report per company. | false |
keywords | In default raw searches, filters titles when no targets and no titleKeyword; in reports, populates keyword_hits. | Empty |
recentWindowDays | Sets the report hiring-velocity window. | 30 |
disableUsageStats | Turns off the run summary described in Usage statistics. | false |
If both companies and presetLists are empty, all four preset lists are searched with duplicate companies removed. The current expansion contains 16 unique companies. A slug is the relevant path or subdomain value from the public careers URL, such as stripe in boards.greenhouse.io/stripe or ramp in jobs.ashbyhq.com/ramp.
Limits and edge cases
| Condition | What the buyer sees | What to do |
|---|---|---|
| Free-plan raw run | At most 10 job rows are delivered; paid plans lift the cap. | Use the returned slice or a paid plan. |
| Free-plan report run with more than one target | Only the first target is searched and at most one report is returned. | Use a smaller batch or a paid plan. |
maxJobsPerCompany is reached | More matching rows are not pushed, but scanning continues and their IDs enter change-detection state. | Raise the value or set it to 0. |
First onlyNewSinceLastRun run | Matching jobs are returned as new and billed, subject to the per-company and Free-plan limits; no closed notices appear. | Keep companies and filters for later delta runs. |
| Later delta run finds changes | Only unseen IDs and closed-job notices are returned; closed notices are not limited by the Free cap. | Keep the same companies and filters. |
| Delta state is stored | SEEN_JOBS in the named multi-ats-job-state store persists between runs and records every fetched ID, including filtered or capped jobs. It is one set per account. | Use the same account, companies, and filters. Omitted companies can appear closed; failed or skipped targets retain earlier IDs. |
| Target is stale, invalid, unsupported, empty, or unreachable | It appears in failedTargets with not_found_or_empty or the error text; reports contain company and reason. | Check the public-board slug, provide the ATS, or retry later. |
| No rows are returned | OUTPUT and the status message explain possible empty boards, unmatched slugs, unreachable boards, filters, or no new jobs. Nothing was charged. | Check OUTPUT, status, failedTargets, targets, and filters. |
| No usable targets are produced | OUTPUT contains error: "no targets" and a message. | Provide companies or a valid presetLists value. |
| Rows are delivered during a run | Rows are pushed company by company and charged after each push; OUTPUT and delta state are written after all companies finish. | Wait for completion before relying on the summary or state. |
| Run is aborted, times out, or fails mid-run | Completed-company rows remain delivered and charged; no OUTPUT summary or delta-state update is written. | The next delta run lists those jobs as new again. |
| 60 seconds or less remain before timeout | No new company fetch starts. Remaining companies appear in OUTPUT.skippedTargets; delta mode does not mark them closed. | Retry the run. |
| Charge call fails | Rows are still delivered and the failure is logged. | Check the run logs. |
reportMode is enabled | The dataset contains reports instead of raw rows; companies with no fetched postings receive no report, and job-result events are not charged. | Set reportMode to false for listing rows. |
FAQ
How much does it cost to scrape job postings?
job-result costs $0.0015 per event on Free, and apify-actor-start costs $0.00005 per event on Free. For 1,000 job results plus one start event, the total is $1.50005 on Free; see Pricing for all plan prices.
What happens if no jobs are returned?
The Actor reports whether the board was empty, no target matched a supported board, filters excluded jobs, or no jobs were new. Check OUTPUT, the status message, and failedTargets.
Why is a company target not working?
Use the slug from its public careers URL and optionally provide the ATS. Without ats, the Actor probes Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters, and Personio. Stale or invalid targets appear in failedTargets.
Does the Actor require a login or API key?
No buyer login or API key is required. The Actor reads the supported ATS platforms' public JSON/XML job-board endpoints; your Apify account runs it and accesses the dataset.
Is using this public job data legal or allowed?
The Actor's source is public job-board data from supported ATS endpoints. Source terms and applicable law depend on your use case, so review the relevant terms and requirements before using the data; public availability is not a legal guarantee.
Usage statistics
This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.
A copy of the exact record for your run is saved as USAGE_STATS in your own Apify key-value store.
To opt out, set disableUsageStats to true in the input. Nothing is sent then.