Career Site Jobs Scraper – Greenhouse, Lever, Ashby, Workday
Pricing
from $3.00 / 1,000 job postings
Career Site Jobs Scraper – Greenhouse, Lever, Ashby, Workday
Monitor job openings of any company list straight from their ATS. Live data, only-new mode for daily hiring-signal alerts, 8 ATS supported. $3 per 1,000 jobs.
Pricing
from $3.00 / 1,000 job postings
Rating
0.0
(0)
Developer
Thongpoo Supong
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Career Site Jobs Monitor (Greenhouse, Lever, Ashby, Workday +4)
Give a list of companies and get their current job openings straight from their ATS. On scheduled runs you can emit only what is new since the last run.
Supported ATS boards (public JSON/XML, no login, no browser):
| ATS | Shorthand example | Board URL example |
|---|---|---|
| Greenhouse | greenhouse:stripe | https://boards.greenhouse.io/stripe |
| Lever | lever:spotify | https://jobs.lever.co/spotify |
| Ashby | ashby:ramp | https://jobs.ashbyhq.com/ramp |
| SmartRecruiters | smartrecruiters:BoschGroup | https://jobs.smartrecruiters.com/BoschGroup |
| Recruitee | recruitee:optics11 | https://optics11.recruitee.com |
| Workable | workable:runware | https://apply.workable.com/runware |
| Personio | personio:personio | https://personio.jobs.personio.de |
| Workday | workday:nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite | https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite |
Input
companies (required, array of strings). Each entry can be:
- ATS board URL — e.g.
https://boards.greenhouse.io/stripe. - Shorthand
ats:slug— e.g.greenhouse:stripe,lever:spotify,ashby:ramp,smartrecruiters:BoschGroup,recruitee:optics11,workable:runware,personio:personio,workday:nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite. - Any careers-page URL — the ATS is detected by scanning the page HTML for known ATS host names.
- A bare company name/slug (guess mode) — tried against the major ATS in order until one returns jobs.
Optional filters:
titleKeywords/excludeTitleKeywords— keep/drop jobs by title keyword.locationKeywords— keep jobs whose location matches any keyword.remoteOnly— only jobs flagged or named remote.postedWithinDays— skip jobs older than N days (whenpostedAtis known).onlyNew— emit only jobs not seen in previous runs (state is stored in the actor's named key-value store).includeDescription(defaulttrue) — set tofalseto save time on SmartRecruiters/Workday by skipping per-job detail calls.maxItemsPerCompany(default 1000) andmaxItems(default 5000) caps.
SmartRecruiters and Workday are fetched in two steps to save money on capped
runs: the list of jobs is fetched first, then per-job detail requests are made
only for the jobs that will actually be pushed (after filters, onlyNew
and the global maxItems budget are applied). A maxItems=1 run therefore
makes exactly one detail request, not one per board job.
Output
One dataset item per job:
| Field | Type | Notes |
|---|---|---|
company | string | input entry exactly as given |
companyName | string|null | from the ATS; falls back to the prettified board slug/tenant when the ATS is silent |
ats | string | greenhouse, lever, ashby, smartrecruiters, recruitee, workable, personio, workday |
boardSlug | string | board slug used for the API |
jobId | string | ATS job id |
title | string | job title |
department, team | string|null | from the ATS |
locations | string[] | one or more locations |
remote | boolean|null | explicit flag or heuristic on the location |
employmentType | string|null | e.g. Full-time |
url, applyUrl | string | canonical posting and apply URLs |
postedAt | ISO string|null | publication date (Workday uses an approximation) |
postedAtRaw | string|null | raw date text (e.g. Workday "Posted 3 Days Ago") |
updatedAt | ISO string|null | last update |
salary | object|null | {min,max,currency,interval} |
descriptionHtml, descriptionText | string|null | null when includeDescription=false |
isNew | boolean | true for items not seen in earlier runs |
scrapedAt | ISO string | when the item was collected |
A run also writes a SUMMARY key-value record with one status row per company
(ok | skipped | not_found | unsupported | blocked | error, plus job counts; skipped = not processed because maxItems or your charge limit was reached). If every
company fails, the run fails loudly instead of returning an empty dataset.
What is NOT collected
No personal data: recruiter / hiring-manager / applicant names, emails,
avatars, application questions, mailbox_email, open_questions or
data_compliance fields are never in the output. Targets are public ATS APIs;
no logins, no CAPTCHA bypass, no proxies.
Scheduling & "only new" recipe
- Run once with
onlyNew: falseto seed the state. - Schedule the actor (e.g. daily) with the SAME
companieslist andonlyNew: true. Only jobs published after the previous run are emitted. - Change the
companieslist whenever your target set changes — state is keyed on the sorted list, so a new list starts fresh automatically.
State entries not seen for 90 days are pruned automatically.
Limits & behaviour
- Per host: max 2 concurrent requests, >=300 ms between requests, 30 s timeout.
- Retries (up to 3) with exponential backoff on transient errors and 429; a
Retry-Afterheader is honoured (capped at 60 s). - A 403, CAPTCHA or JS-challenge page is recorded as
blockedand never retried. - Items are validated against the output schema; if more than 20% fail, the run fails loudly so a board layout change is never reported as "no jobs".
Development
npm installnpm test # offline, fixtures only