Job Scraper | Greenhouse, Lever, Ashby & More
Pricing
from $0.70 / 1,000 delivered jobs
Job Scraper | Greenhouse, Lever, Ashby & More
Scrape jobs from Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters and Personio. Export descriptions and locations, track new or closed postings, and generate company hiring reports.
Pricing
from $0.70 / 1,000 delivered jobs
Rating
0.0
(0)
Developer
tingyou333 zhuang
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrape jobs from Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters and Personio. Export descriptions and locations, track new or closed postings, and generate company hiring reports.
Useful for: Monitor selected company career boards; build a job feed; compare hiring activity across ATS providers.
Why choose this Actor: Use one input format for six ATS providers. Collect jobs or company hiring reports, with persistent change tracking and source coverage for repeat runs.
Try a small sample
- Click Try for free, then open Input and switch to JSON.
- Paste the example below and click Start. It uses a small result limit.
- Open the dataset to inspect results, then export JSON, CSV or Excel. Source restrictions can still cause partial or failed runs.
{"companies": [{"ats": "greenhouse","company": "stripe"}],"maxJobsPerCompany": 5,"includeDescriptions": true,"outputProfile": "full"}
Cost at a glance
Primary billing unit: Delivered job. Rates below are per 1,000 primary events.
| Free plan | Starter / Bronze | Scale / Silver | Business / Gold and higher |
|---|---|---|---|
| $1 | $0.9 | $0.8 | $0.7 |
Platform compute, proxy, transfer and storage are additional. Other event types, where enabled, are listed in the Pricing tab. “Try for free” uses available account credits; it does not make usage unlimited or unmetered.
Coverage to know: Use an explicit provider and company slug for your first run. Closed-job detection requires complete successful snapshots; it is not a full-market jobs database.
For Workday career sites, see our companion Actor. It runs and bills separately.
Guides and full reference
Collect public Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters and Personio job feeds, or produce one hiring report per company. Supports scheduled monitoring with explicit source coverage and delivery reports.
Omit ats to probe all six providers. Empty auto-detected feeds do not establish company identity. The verified Recruitee tellent board maps to careers.tellent.com regardless of slug letter case; supplied company labels and global-ID casing are preserved for compatibility. Use consistent slug spelling across scheduled runs and avoid submitting case variants as separate targets; arbitrary custom hosts are not supported yet. Personio supports .de and .com XML feeds. Source failure is reported in OUTPUT.failedTargets, not represented as a successful empty board.
Inputs and output
titleKeyword and locationKeyword apply case-insensitive substring filters before maxJobsPerCompany. remoteOnly includes only jobs classified as fully remote; hybrid does not qualify. Zero maxJobsPerCompany removes the output cap. Disabling includeDescriptions removes both HTML and plain text; raw source blobs are not exposed through an alternate field. outputProfile accepts full, compact (no HTML), or minimal (core fields).
The four explicit presetLists are:
top-tech: Stripe, Spotify, OpenAI.ai-ml: Anthropic, OpenAI.devtools: Postman.fintech: Stripe, Ramp.
These starter bundles are not exhaustive rankings and may differ from other Actors' memberships. Combine them with explicit companies; duplicate ATS/company pairs merge. Pin explicit companies if you need a fixed target universe.
Persistent changes
onlyNewSinceLastRun compares complete successful source snapshots. New and closed observations carry stable global_id, is_new, and is_closed fields. Pending new jobs survive output caps and refresh from the latest source data before delivery. Failed or incomplete fetches do not close jobs or replace snapshots. State scope separates company/provider/filter combinations.
Stateful runs use a server-managed lease. Overlapping runs fail with STATE_BUSY. An aborted or crashed owner can leave its lease held for up to 300 seconds after the last renewal, even when Console already shows a terminal run. The error report recommends retryAfterSeconds: 300; if another owner is still running, wait for it as well. Do not delete the lock to force access. A crashed owner's lease expires. Snapshot chunks are immutable and hash-checked; the manifest changes only after every chunk is saved. Old snapshots are readable during migration.
Dataset delivery and snapshot acknowledgement are not a single transaction. A crash between them can replay a delivered event; consumers must deduplicate. Disabled descriptions are not retained in new snapshot records, so historical closed-job descriptions may be unavailable after changing that setting. A write-ahead journal allows the next successful snapshot write to reclaim interrupted chunk uploads. Committed obsolete chunks are deleted after the new manifest commits; failed deletions remain retryable. Historical orphan chunks created before journaling are not automatically enumerated. Dataset delivery still has the replay boundary described above.
Hiring reports
Set reportMode: true for one report per company over the complete filtered snapshot, independent of the job output cap. Reports include role families, departments, location labels, remote share, seniority mix, keyword counts, publication dates and observed changes. keywords selects whole-word title matches; recentWindowDays defaults to 30.
First observations have unknown growth. Publication-window counts and changes since the prior observed snapshot are separate. The score is min(100, round(20 * log2(1 + open_roles))): a transparent posting-volume index, not a forecast or a reproduction of an undisclosed competitor formula. Region fields group fully remote roles as remote, otherwise use explicit country fields or an unambiguous country name in the location text. Unmapped or ambiguous locations are other; city/state abbreviations are not guessed as countries. location_signals preserves the original location breakdown. These explicit rules do not reproduce an undisclosed competitor classifier. Suggested outreach is draft guidance only; this Actor sends no messages.
Pricing and current limits
Pay-per-event pricing applies for delivered job records and delivered hiring reports. Each report incurs one event, not one event per summarized job. Per 1,000 events: FREE $1.00; BRONZE $0.90; SILVER $0.80; GOLD/PLATINUM/DIAMOND $0.70. Platform usage is additional and depends on source size, descriptions, retries and state activity. There is no custom start event. Failed targets have no result/report event charge. See the Pricing tab for current rates. Stateful job delivery has passed cloud event-count checks, including a second run that delivers pending jobs without repeating the previous result. These checks validate owner event accounting, not customer revenue or all report billing scenarios. No total-cost superiority is claimed.
Broader detail coverage and total-cost comparisons remain workload-dependent. Snapshot fault recovery and six-provider pagination samples have bounded evidence; process-level exactly-once delivery is not claimed. Inspect the run output and source coverage for your workload. Do not infer full parity or reliability from successful sample runs.
Field interpretation
compensation preserves structured salary tiers/ranges where published. salary contains the published summary or the original currency, bounds and period. No currency conversion or invented salary estimates are applied. Recognized native seniority codes take priority over title patterns; seniority_evidence and source_seniority explain the choice. Unmapped codes remain available, with title inference as a fallback.
parse_confidence is an eight-field structural coverage score: ID, title, URL, location, publication date, department, employment type and recognized remote type. Each contributes equally. field_coverage exposes the checks and parse_confidence_method names the formula. This is not a calibrated probability, a description-completeness score, or proof that the source's claims are accurate. Optional absent fields can lower the score even when parsing succeeded.
API example
Set APIFY_TOKEN in your own environment and run an asynchronous request:
curl --request POST \"https://api.apify.com/v2/acts/peerless_columbine~multi-ats-jobs-scraper/runs" \--header "Authorization: Bearer $APIFY_TOKEN" \--header "Content-Type: application/json" \--data '{"companies":[{"ats":"ashby","company":"ashby"}],"maxJobsPerCompany":10}'
The returned data.id identifies the run. Poll GET /v2/actor-runs/{runId} until terminal. On success, download GET /v2/datasets/{defaultDatasetId}/items?format=json. Also read GET /v2/key-value-stores/{defaultKeyValueStoreId}/records/OUTPUT for per-target counts and failures. Partial failures can coexist with successful dataset rows. Use your own Apify account token. Never put a personal token in shared input or public code.
Verified output example
This excerpt was captured from a successful private cloud run; source jobs can change later. Full mode also returns descriptions and structured compensation where available.
{"ats": "recruitee","company": "tellent","title": "Customer Success Manager - DACH","location": "Amsterdam, Noord-Holland, Netherlands","country": "Netherlands","remote_type": "hybrid","seniority": "mid","seniority_evidence": "source","salary": "EUR 55000 - 60000 year","job_id": "2735044","global_id": "recruitee:tellent:2735044","url": "https://careers.tellent.com/o/customer-success-manager-dach-4","posted_at": "2026-09-07T07:42:58+00:00","parse_confidence": 1,"parse_confidence_method": "typed_field_coverage_v1; not calibrated accuracy probability"}
In the Dataset tab, select Jobs, Hiring reports, or Field coverage for the corresponding output. A hiring report has no job title or job ID; job rows have no report totals, so choose the view matching the run mode.
Publication dates are normalized to ISO 8601 UTC; source_posted_at preserves the original value. Missing dates remain null. Unparseable values carry a warning; timezone-free dates explicitly carry publication_timezone_assumed_utc. Recent-window statistics exclude unparseable dates and future dates.
Report snapshots retain country and remote-type fields for stable region comparisons. Older snapshots without these fields cannot prove regional expansion: region_comparison_available is false until a new baseline is saved.
Viewing run reports
In the Output tab, select Run reports and failed targets and open or download the OUTPUT record from the native file list. It contains acknowledged rowsSaved, per-target counts, snapshot status and failedTargets. The summary run-output link now opens this record list; API clients that need JSON should request GET /v2/key-value-stores/{defaultKeyValueStoreId}/records/OUTPUT directly. That record path and the dataset results link are unchanged.
A priced job is acknowledged in incremental state only when the SDK accepts its delivery. A job rejected by the event budget stays pending for a later run. Previously delivered jobs are not re-emitted during ordinary continuation; a crash between dataset delivery and state commit can still cause a replay. An interrupted run may lack a final OUTPUT record, so also inspect run status and available dataset rows.
Run limits and measured costs
The default run timeout is 3,600 seconds with 1,024 MB memory, matching the reference Actor's published run defaults. Console/API overrides take precedence. A longer timeout permits large source and detail requests to finish; it does not guarantee success or limit fees.
maxJobsPerCompany limits delivered job rows, not source work. Every selected board is collected completely before filtering and state comparison. In particular, SmartRecruiters with descriptions enabled requests one detail per source job, even when the output cap is small. For an initial metadata check, choose one explicit company/provider and disable descriptions.
Measured private samples, modeled at public Starter/Bronze resource tariffs and current event rates:
| Workload | Event fees | Run resources | Marginal total |
|---|---|---|---|
| First stateful run, 1 delivered job | $0.000900 | $0.000881 | $0.001781 |
| Same-scope continuation, 2 delivered jobs | $0.001800 | $0.001364 | $0.003164 |
| One report over 618 source jobs | $0.000900 | $0.000689 | $0.001589 |
These samples used 512 MB explicit test overrides and disabled descriptions. They are not estimates for every default run. Tiny incremental outputs still pay full-snapshot and lease overhead; lower result prices do not establish lower total cost. Figures exclude monthly plan commitment, taxes, post-run exports and time-based retention. They are quantity-based models, not customer invoices. See Apify resource pricing.
Lever salary output uses published plain text when available, strips markup from an HTML-only summary, and otherwise formats the native salaryRange currency, bounds and interval. A single bound is labeled “from” or “up to”; absent or invalid ranges stay unknown. The original structured range remains in compensation. Lever's published country code is retained for report geography instead of guessing a country from a city. See the official Lever fields.
Geographic change detection versions its interpretation rules. After an upgrade that changes country extraction or region classification, the first successful report records a fresh geography baseline and sets region_comparison_available: false with no asserted new_regions. Existing job-ID and role-count comparisons still work. A subsequent report using the same rule version can compare regions again. This prevents newly populated country fields from being presented as business expansion.
When ATS auto-detection finds one working provider, other attempted providers may still fail or return an unconfirmed empty feed. OUTPUT.providerIssues preserves those attempts even if the overall company has results. targetHandled means a provider succeeded or was skipped at the delivery budget; consult targets for actual collected counts and limit flags. A 404 for an unused platform is common during auto-detection and is not proof that jobs are missing. Transport/server errors on another provider leave that provider's coverage unverified. failedTargets retains its original meaning: company targets with no successful provider. Inspect both arrays instead of treating a successful run as proof that every provider was collected.
All six providers validate unique source job identities before either job delivery or hiring-report aggregation. Duplicate IDs fail that provider snapshot instead of inflating report counts or silently choosing a conflicting record. Failed provider snapshots do not update their persistent baseline.
Career-link input convenience
Existing { "ats": "greenhouse", "company": "stripe" } inputs remain unchanged.
Alternatively, supply boardUrl inside a company item:
{"companies": [{ "boardUrl": "https://job-boards.greenhouse.io/stripe" },{ "boardUrl": "https://careers.tellent.com" }],"maxJobsPerCompany": 2,"includeDescriptions": false}
Recognized hosts are boards.greenhouse.io, job-boards.greenhouse.io,
jobs.lever.co, jobs.ashbyhq.com, jobs.smartrecruiters.com, company subdomains
of recruitee.com and jobs.personio.de/jobs.personio.com, plus the verified
careers.tellent.com mapping. Individual job links on these hosts can also supply
the company slug. SmartRecruiters company spelling is preserved.
This extracts the standard ATS/slug target, not an arbitrary URL fetch. Normal
provider routing applies, including Personio's .de feed followed by .com on
404. URL query filters, locale and job-ID path suffixes do not restrict the board
collection; use the Actor's filters for output. Unsupported hosts, credentials,
ports and conflicting explicit ATS/company values are rejected before collection.
Matching URL-derived and existing slug targets merge, retaining the same IDs and
state scope. Case variants follow the existing spelling rules described above.
Report recommended_outreach remains an array of suggestion strings. It now considers observed net vacancy growth, newly observed departments/regions/role families, management and executive vacancies, and the top three role concentrations. First observations never assert growth; geography changes require a comparable report baseline. Empty boards produce no suggestions. The additional outreach_signals array links each suggestion to its count, category, or title examples. These are hiring observations and suggestions, not evidence of company revenue, allocated budgets, purchasing authority, or verified expansion of the business. Nothing is sent to contacts. Competitors already offer trend-based suggestions; the structured evidence is our inspectable implementation, not a claim of exclusive functionality.
Output field contract
The dataset schema documents 50 job and report fields, including nullable source values, numeric ranges and array item types. Only ats and company are required across both record families. Job/report-specific fields are optional in the shared schema: absence is expected when a mode does not return them. New fields remain allowed for compatible extension. The schema documents types; it is not proof of source completeness or an automatic runtime rejection mechanism.
| Record or setting | Fields to expect |
|---|---|
| Job identity | ats, company, global_id, title, url; full/compact also include source job_id |
| Optional source data | salary, posted_at, department, country and other source fields can be null when unknown |
| Minimal jobs | Core identity, location, remote flag, seniority and date; delta flags when applicable |
| Compact jobs | Full job fields except description_html |
| Descriptions disabled | Neither description field is returned, including through raw source data |
| Delta jobs | Boolean is_new and is_closed; a closed observation retains available prior values |
| Hiring report | record_type: hiring_signal_report, counts, score method, breakdowns and observed-change objects; no job identity fields |
| Report suggestions | recommended_outreach strings and matching outreach_signals objects with structured evidence |
Remote share and structural field coverage are numbers from 0 to 1. Vacancy counts are nonnegative integers. Unknown first-observation changes remain null inside the corresponding report objects. Native compensation structures vary by provider and are preserved rather than forced into an invented common salary format. Use the Input/Output documentation and select the dataset view for the run mode; a job table will not show report-only fields.
Title-based seniority is an inference, not a verified reporting hierarchy. In particular, account, customer-success, product, project, program, engagement, partner/partnership, business-development, community and campaign “manager” titles alone do not establish people-management responsibility. Such titles retain another explicit level marker (for example, Senior) or unknown seniority, with people_management_not_established_by_title in warnings. Recognized native ATS levels still take priority. Other management/executive title patterns also remain inferences; report leadership counts describe classified postings, not a verified count of hiring managers or budget owners. This corrects the previous broad Manager-title classification; historical stored job observations are not rewritten.
First-run delta behavior
With onlyNewSinceLastRun: true, firstRunMode: "emit" preserves the existing default: current jobs are initially new, and undelivered jobs remain pending across result limits. Choose firstRunMode: "snapshot" to collect and persist the first complete baseline without emitting or charging initial job results. Subsequent runs emit genuinely new and closed observations, including changes after an initially empty board. Source collection, storage and platform usage are still charged; zero result events does not mean a free run.
Snapshot mode has its own persistent state scope. Switching an existing emit-mode task to snapshot mode creates a fresh baseline; it does not overwrite or import the old task's pending events. Return to emit mode to resume that original scope. This setting is ignored in report mode and ordinary non-delta job runs. Failed/incomplete sources do not establish a baseline. OUTPUT.targets[].initialSnapshot indicates a successful snapshot-only initialization.
The reference Actor describes its first delta run as taking a snapshot. This explicit option supports that workflow; paid execution of the competitor has not established whether it also emits initial rows, so exact first-run runtime equivalence is not claimed.