Job Board Scraper — Greenhouse, Lever, Ashby & Workday avatar

Job Board Scraper — Greenhouse, Lever, Ashby & Workday

Pricing

from $2.00 / 1,000 job scrapeds

Go to Apify Store
Job Board Scraper — Greenhouse, Lever, Ashby & Workday

Job Board Scraper — Greenhouse, Lever, Ashby & Workday

Aggregate public ATS job boards across Greenhouse, Lever, Ashby and Workday: normalize, dedupe, and emit hiring signals. Public endpoints only; PII fields filtered.

Pricing

from $2.00 / 1,000 job scrapeds

Rating

0.0

(0)

Developer

easy-ok

easy-ok

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Categories

Share

Job Board Scraper — Greenhouse, Lever, Ashby & Workday (ATS Aggregator)

A single job scraper that aggregates public jobs data across four major applicant tracking systems — Greenhouse, Lever, Ashby and Workday — then normalizes every posting into one schema, de-duplicates roles that appear on more than one board, and (in monitor mode) emits hiring signals when a company opens or closes reqs.

It reads only official, public job-board endpoints (the same JSON these career sites load in your browser). It does not touch any login-gated page and it filters personal data out of the output by design.

  • Greenhouse APIboards-api.greenhouse.io public board API
  • Lever postingsapi.lever.co/v0/postings public postings API
  • Ashbyapi.ashbyhq.com/posting-api/job-board public posting API
  • Workday scraper — public /wday/cxs/{tenant}/{site}/jobs career-site search endpoint

Use cases

  • B2B sales & market intent — "who is hiring a Salesforce admin / a Kubernetes SRE / a RevOps lead right now" is a strong buying signal. Monitor mode turns new reqs into jobs_added events you can route to sales.
  • Recruiting & talent mapping — track competitor headcount plans and open roles by department and location across every ATS at once.
  • Salary / compensation research — capture salary_min / salary_max where the board exposes it (Ashby and Lever frequently do; pay-transparency roles on others).
  • Job-board aggregation — build a clean, de-duplicated jobs feed from many companies and many ATS platforms without writing four different scrapers.

Input

{
"targets": [
{ "ats": "greenhouse", "token": "stripe", "company": "Stripe" },
{ "ats": "lever", "token": "palantir", "company": "Palantir" },
{ "ats": "ashby", "token": "ramp", "company": "Ramp" },
{ "ats": "workday", "token": "salesforce", "company": "Salesforce",
"workday": { "host": "salesforce.wd12.myworkdayjobs.com", "tenant": "salesforce", "site": "External_Career_Site" } }
],
"includeDescription": false, // true = add PII-scrubbed plain-text description (max 5000 chars)
"mode": "snapshot", // "snapshot" | "monitor"
"maxJobsPerTarget": 0 // 0 = all public postings
}

Finding the token/host for each ATS

ATStoken is…Extra
greenhouseboard token in boards.greenhouse.io/<token>
leverslug in jobs.lever.co/<token>
ashbyslug in jobs.ashbyhq.com/<token>
workdaytenant namealso set workday.host / workday.tenant / workday.site from the public career-site URL https://<host>/<lang>/<site>

Output

Every job is normalized to the same whitelist of fields (no raw source JSON is ever passed through):

{
"ats": "ashby", "company": "Ramp",
"job_id": "…", "canonical_key": "sha1(company|title|location)",
"title": "Customer Activation Manager | Enterprise",
"department": "Sales", "team": null,
"location": "New York", "locations": ["New York", "Remote (US)"], "remote": false,
"salary_min": 147000, "salary_max": 262000, "salary_currency": "USD",
"posted_at": "2026-05-11T12:47:52.238Z", "updated_at": null,
"url": "https://jobs.ashbyhq.com/ramp/…",
"description_text": null,
"sources": [ { "ats": "ashby", "company": "Ramp", "job_id": "…", "url": "https://…" } ]
}

De-duplication & hiring signals

De-dupe. The same role can appear multiple times (posted per-shift, or listed on two ATS during a migration). Items sharing a canonical_keysha1(company | normalized_title | primary_location) — collapse into the single most complete record, and every origin is kept in sources[].

Monitor mode. Set "mode": "monitor". The actor stores a per-company snapshot (the set of canonical_keys) in a persistent key-value store and, on the next run, emits signal items:

{ "type": "signal", "event": "jobs_added", "company": "Stripe", "count": 5, "titles": ["…"], "total_active": 123, "ts": "…" }
{ "type": "signal", "event": "jobs_removed", "company": "Stripe", "count": 2, "titles": ["…"], "total_active": 123, "ts": "…" }

Job items have no type field; signal items are tagged "type": "signal" and operational records (a board that could not be fetched) are tagged "type": "status", so all three are easy to filter apart in the dataset.

Compliance

  • Public endpoints only. The actor calls the official, public job-board APIs that these career sites serve to anonymous browsers. It never accesses /admin, applicant, or any login-gated page, and for Workday it only calls the public CXS search endpoint — never an authentication host.
  • Personal data is filtered out. Output is a strict field whitelist: recruiter names, contact emails and similar fields are never mapped. When includeDescription is enabled, the description text is additionally run through an email/phone scrubber before it is stored.
  • robots.txt is fetched and logged for each host as a courtesy trace.
  • Your responsibility. You should review each ATS provider's Terms of Service and each target company's terms before scraping at scale, and confirm your use complies with applicable law (including data-protection rules in your jurisdiction). This actor is a tool; how you use it is up to you.

FAQ

Which ATS platforms are supported? Greenhouse, Lever, Ashby and Workday public boards.

Do I need an API key or login? No. Only public endpoints are used; no authentication.

Does it use a headless browser? No — it is pure HTTP/JSON, which is fast and cheap.

Can it fetch full job descriptions? Yes, set includeDescription: true. Descriptions are converted to plain text, scrubbed of emails/phone numbers, and truncated to 5000 characters.

How does Workday pagination work? The actor pages the public CXS endpoint 20 results at a time. Workday only returns the true total on the first page, which the actor accounts for.

What if one company or ATS fails? Each target is isolated — a failure is recorded as a status item (e.g. endpoint_unavailable, rate_limited, workday_probe_failed) and the run continues.

Local development

npm install
npm test # unit tests (sanitize / normalize / dedupe / signals / schema)
npm run typecheck
apify run # or: npx tsx src/main.ts (reads storage/key_value_stores/default/INPUT.json)