Career Site Job Scraper: Greenhouse, Lever, Ashby, Workday avatar

Career Site Job Scraper: Greenhouse, Lever, Ashby, Workday

Pricing

from $1.50 / 1,000 job results

Go to Apify Store
Career Site Job Scraper: Greenhouse, Lever, Ashby, Workday

Career Site Job Scraper: Greenhouse, Lever, Ashby, Workday

Get every open job from company career sites on Greenhouse, Lever, Ashby, Workday and SmartRecruiters via their public job-board feeds. Normalized fields, salary ranges, clean descriptions, filters, and new/closed job tracking between runs. $1.50 per 1,000 jobs.

Pricing

from $1.50 / 1,000 job results

Rating

0.0

(0)

Developer

Naveen Raja

Naveen Raja

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Career Site Job Scraper & API: Greenhouse, Lever, Ashby, Workday + new/closed job tracking

Get every open job from company career sites that run on Greenhouse, Lever, Ashby, Workday and SmartRecruiters, in one clean JSON format. The Actor reads the public job-board feeds that the companies' own careers pages use, so the data is complete, current and fast to fetch. No browser, no login, no proxy.

Switch on change tracking and every later run tells you which jobs are new and which were closed (taken down) since the previous run. Schedule it daily and you have a hiring monitor.

Price: $1.50 per 1,000 jobs ($0.0015 per job) plus $0.0005 per run. You pay only for job rows returned; Apify platform costs are included.

What you runCost
100 jobs$0.1505
Every open job at a 700-role company (e.g. Stripe)about $1.10
Daily "only new and closed" monitor of 20 companies (~50 changes a day)about $0.08 a day

What you get

  • One normalized item per job, same fields for every ATS: company, title, department, team, locations, remote status, workplace type, employment type, posted date, job URL, apply URL, salary range (when the company publishes one) and an optional clean-text job description.
  • New / existing / closed status for each job when tracking is on, with the time we first saw the job.
  • Filters: keywords, excluded words, locations, departments, remote only, posted in the last N days.
  • Paste careers-page URLs and the ATS is detected for you, or use short ats:slug entries.
  • Built for automation and AI agents: predictable schema, pay-per-event pricing with no usage fees, works with limited permissions, a run summary record, and a clean stop when your spending limit is reached.

Supported job boards

ATSExample inputWhat the ATS publishes
Greenhousehttps://job-boards.greenhouse.io/stripe or greenhouse:stripeTitle, department, location, first published / updated dates, pay ranges (pay transparency), description
Leverhttps://jobs.lever.co/palantir or lever:palantir (EU boards on jobs.eu.lever.co too)Title, team, department, all locations, workplace type, commitment, created date, salary range, description
Ashbyhttps://jobs.ashbyhq.com/openai or ashby:openaiTitle, department, team, primary + secondary locations, remote flag, workplace type, employment type, published date, compensation, description
Workdayhttps://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite or workday:nvidia.wd5/NVIDIAExternalCareerSiteTitle, all locations, time type, start/posted date, remote type (some sites), description
SmartRecruitershttps://jobs.smartrecruiters.com/ServiceNow or smartrecruiters:ServiceNowTitle, department, function, location with remote/hybrid flags, employment type, release date, description

You can also paste a company's own careers page (for example https://www.figma.com/careers/). The Actor opens that page once and looks for an embedded Greenhouse, Lever, Ashby, Workday or SmartRecruiters board. This works for many sites but not all (some pages are built entirely in JavaScript or block automated visits); if it fails, the run summary tells you to pass the ATS URL instead.

Use cases

  • Job boards and aggregators: pull complete, fresh listings straight from employers' career sites.
  • Hiring signals for sales and investing: see which companies are hiring for which teams and where, and get alerted when new roles open or close.
  • Recruiting and talent intelligence: track competitors' open roles, locations and published salary ranges.
  • Job alerts: schedule a daily run with keywords and "Return only new and closed jobs" to get just the changes.
  • AI agents and LLM apps: give an agent a reliable tool to answer "Is Stripe hiring data engineers in Dublin?" with structured data.

How to use

  1. Add companies in Companies (one per line). Careers-page URLs or ats:slug entries both work.
  2. Optional: add filters (keywords, locations, departments, remote only, posted within N days).
  3. Choose whether to include the job description (on by default).
  4. Optional: turn on Track new and closed jobs. Use the same Tracking ID on every run of the same monitor.
  5. Run the Actor and download the results as JSON, CSV, Excel or via API. A per-company summary is saved as the SUMMARY record in the run's key-value store.

The same board entered twice (for example greenhouse:stripe and https://job-boards.greenhouse.io/stripe, or a careers page that leads to a board you also listed) is read and charged once. An entry that returns no jobs because of a problem (a wrong slug, no board found on a careers page, an error at the job board) gives one free error row in the dataset with status: "error", the input, an errorKind and the reason in error.

Input example

{
"companies": [
"greenhouse:stripe",
"https://jobs.lever.co/palantir",
"ashby:openai",
"https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
"smartrecruiters:ServiceNow"
],
"keywords": ["engineer", "data"],
"locations": ["San Francisco", "Remote"],
"includeDescription": true,
"maxJobsPerCompany": 0,
"trackChanges": true,
"onlyNewAndClosed": false,
"trackingId": "my-hiring-monitor"
}

Output example

A real item from a test run in October 2026 (Ramp on Ashby, with Remote jobs only; description shortened):

{
"company": "ramp",
"companySlug": "ramp",
"ats": "ashby",
"jobId": "d1183b00-6590-4fe4-a585-28d84e578fe3",
"uid": "ashby:ramp:d1183b00-6590-4fe4-a585-28d84e578fe3",
"title": "Software Engineer, Security, Stablecoin",
"department": "Engineering",
"team": "Backend",
"locations": [
"New York, NY (HQ)",
"San Francisco, CA",
"Remote (US)"
],
"remote": true,
"workplaceType": "remote",
"employmentType": "Full-time",
"postedAt": "2026-05-13T20:28:09Z",
"updatedAt": null,
"url": "https://jobs.ashbyhq.com/ramp/d1183b00-6590-4fe4-a585-28d84e578fe3",
"applyUrl": "https://jobs.ashbyhq.com/ramp/d1183b00-6590-4fe4-a585-28d84e578fe3/application",
"compensation": {
"min": 189000,
"max": 330000,
"currency": "USD",
"interval": "year",
"summary": "$189K – $330K • Offers Equity"
},
"status": "new",
"firstSeenAt": "2026-10-19T22:37:26Z",
"scrapedAt": "2026-10-19T22:37:26Z",
"input": "ashby:ramp",
"error": null,
"errorKind": null,
"descriptionText": "About Ramp\n\nRamp is building the smart infrastructure for finance teams, embedded in the transaction flow of every dollar a business spends. We automa ..."
}

A closed job (tracking on) has the same shape with "status": "closed". It keeps the title, locations, department, team, URLs, remote status, workplace type and firstSeenAt saved when the job was first returned; the other fields are null because the posting no longer exists. (For jobs saved by builds before 1.1.2, remote is recomputed from the saved locations, often null, and workplaceType is null; their closures are always reported, also with Remote jobs only or the location "Remote", because the monitor returned those jobs before.)

An error row (free) has "status": "error", the input it belongs to, errorKind (not_found, invalid_input, no_board_found, careers_page_unreadable, source_error or internal_error) and error (what went wrong and what to do); the job fields are null.

Output fields

FieldDescription
company, companySlug, atsCompany name as published by Greenhouse and SmartRecruiters. Lever, Ashby and Workday don't publish a company name, so for them it is the board name (the slug, e.g. openai, or the Workday tenant, e.g. nvidia). Then the board identifier and the ATS
jobId, uidJob ID on the ATS, and a globally unique ats:companySlug:jobId key
title, department, teamAs published by the company
locationsList of location strings
remotetrue: remote (see "Remote jobs" below). false: the ATS says hybrid or on-site. null: the ATS doesn't say
workplaceTyperemote / hybrid / onsite as published by the ATS, otherwise null
employmentTypeFull-time, Part-time, Contract, Internship, ...
postedAt, updatedAtISO 8601 (UTC). Workday gives a date only. Lever and Ashby have no update date
url, applyUrlJob page and application page
compensation{min, max, currency, interval, summary} or null
descriptionTextClean plain-text description (when Include job description is on)
statusopen (tracking off), new / existing / closed (tracking on), or error (free error row)
firstSeenAt, scrapedAtWhen this tracker first returned the job, and when this run read it
inputThe company entry from your input that produced the row
error, errorKindError rows only (null on job rows): why the entry returned no jobs

The dataset has ready-made views: Jobs, New & closed, Compensation, Errors and All fields. Apify views can't hide rows, so error rows also appear in the job views as nearly empty rows with status error. To keep only jobs, skip rows whose status is error (in a spreadsheet, filter the Status column; in code, [r for r in items if r["status"] != "error"]). Failed entries are also listed in the SUMMARY record.

Remote jobs

The remote field and the Remote jobs only filter follow the same rules for every ATS:

  1. A workplace type published by the ATS wins. Hybrid and on-site jobs are remote: false, even when the ATS also flags them as remote-eligible (Ashby sets isRemote: true on hybrid postings) or one of their locations says "Remote".
  2. Without a workplace type, an explicit remote flag from the ATS decides (Ashby isRemote).
  3. Otherwise a location that clearly says remote ("Remote", "US-Remote", "Remote - Canada", "Remote-Friendly, United States") gives remote: true (with workplaceType: null, because a location such as "US-SF, US-NYC, US-Remote" means remote is possible, not that the job is fully remote).
  4. Otherwise the remote status is unknown: remote: null. We don't guess from the description text.

What each ATS publishes: Lever, SmartRecruiters and most Ashby boards give a workplace type for every job. Greenhouse gives one only when the company adds it as a custom field (many don't), and Workday only on sites that publish a "remote type". On those boards, jobs without a "Remote" location are null. Remote jobs only keeps remote: true jobs; tick Remote only: also keep jobs with unknown remote status to also get the null ones and check them yourself. The location filter value "Remote" works like Remote jobs only, including that option.

How change tracking works

With Track new and closed jobs on, the Actor saves the jobs it has returned for each company in a named key-value store in your Apify account (career-site-jobs-tracking, one record per company and Tracking ID). On the next run:

  • new: on the board now and not returned before by this tracker
  • existing: returned in an earlier run and still on the board
  • closed: returned in an earlier run and no longer on the board (it is output once, then forgotten)

Good to know:

  • The first run marks every job as new.
  • Return only new and closed jobs skips existing jobs, so a daily monitor costs you only for the changes. Ticking it turns change tracking on by itself.
  • Jobs that don't match your filters are not stored, so if you widen the filters later, newly matching jobs show up as new.
  • Closed jobs are reported only when the whole board could be read in that run (for example not when a very large Workday site could not be read completely). If a run stops early because of your spending limit, unreported changes are kept and reported next time.
  • Use different Tracking IDs for independent monitors (for example one per team or per filter set).

Pricing

Pay per event, no subscription and no extra usage fees:

EventPrice
job: one job row in the dataset (open, new, existing or closed)$0.0015 ($1.50 per 1,000)
Actor start (standard Apify event, per run; one event per GB of memory, so 1 at the default 512 MB)$0.0005

Examples: all 731 open jobs at Stripe cost about $1.10. A daily "only new and closed" monitor of 20 companies that sees 50 changes a day costs about $0.08 per day.

  • Apify platform costs (compute, storage, data transfer) are included in the price.
  • Free: error rows, the run summary (SUMMARY record), duplicate board entries (read once), and jobs whose detail page could not be loaded (skipped, not charged).
  • Set Maximum cost per run in the run options (or maxTotalChargeUsd via API) to cap spending. The Actor stops cleanly when the cap is reached: it stops listing boards and loading job details as soon as it can't charge for more rows, and everything returned up to that point is in the dataset.
  • If Apify moves a run to another server mid-run, it continues where it stopped and never returns or charges a job twice.

Changes in version 1.1 (20 Oct 2026)

What existing users may notice:

  • Error rows in the dataset. An entry that returns no jobs because of a problem now gives one free row with status: "error", input, error and errorKind; all job fields are null. To keep only jobs, skip rows whose status is error. Every row now has the keys input, error and errorKind (so CSV/Excel exports have three more columns; error and errorKind are null on job rows).
  • Remote status. remote is null (unknown) instead of false when the job board doesn't say, and hybrid or on-site jobs are always false (Ashby hybrids used to be true). Remote jobs only and the location value "Remote" now return only remote jobs; tick Remote only: also keep jobs with unknown remote status to include the unknown ones.
  • workplaceType is only what the job board publishes: Greenhouse jobs that are remote only according to their location text now have workplaceType: null (was remote).
  • Board ids. Greenhouse and Ashby slugs are lower-case in companySlug and uid (greenhouse:Figma gives greenhouse:figma:…), and SmartRecruiters uses its own spelling of the company id (ServiceNow). The same board entered twice is read and charged once. Change tracking keeps working: records saved by version 1.0 under the old spelling are taken over on the first 1.1 run, so jobs stay existing.
  • Tracking. Return only new and closed jobs now turns change tracking on by itself (it creates the career-site-jobs-tracking store).
  • Run status. A run where every entry fails because of the input (for example a wrong slug) now ends as succeeded, with the error rows explaining why.

Use it from the API, an app or an AI agent

Run synchronously and get the items in one call (keep your own API token in the APIFY_TOKEN environment variable):

curl -X POST "https://api.apify.com/v2/acts/fairfetch~career-site-jobs-api/run-sync-get-dataset-items?maxTotalChargeUsd=0.50" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companies": ["greenhouse:stripe"], "keywords": ["data"], "includeDescription": false}'

The Actor runs with limited permissions and pay-per-event pricing without usage fees, so AI agents can call it through the Apify MCP server and pay per run. Each run also writes a machine-readable SUMMARY record with per-company counts and errors.

Performance and limits

  • Greenhouse, Lever, Ashby and SmartRecruiters boards are read with one request per board or per 100 jobs. In our tests a 700 to 800-job board took 10 to 50 seconds, and 5,288 jobs from five companies took 2.5 minutes (without descriptions).
  • Max jobs per company returns the newest jobs on every ATS. Greenhouse and Ashby send the whole board in one response, and Lever boards are always read in full because Lever doesn't list jobs by date. Workday and SmartRecruiters list newest first, so without filters or tracking only the first pages are read.
  • Workday and SmartRecruiters need one extra request per job for the description, so large boards with descriptions take longer (roughly 1 to 2 jobs per second per company). Turn off Include job description for speed.
  • Workday search returns at most 2,000 jobs per query. For bigger sites the Actor automatically splits the query by job category, so you still get the full board (tested: 2,735 NVIDIA jobs). If a split can't cover the whole site, the run says so in SUMMARY and skips closed-job detection for it, so no job is wrongly reported as closed.
  • Requests are polite: at most 3 at a time per host, automatic retries with exponential backoff for errors and rate limits, and timeouts.
  • Fields depend on what each company publishes. For example, many Greenhouse boards don't publish employment type, and Workday sites don't publish departments (the department filter is skipped for Workday).

FAQ

Do I need an account with Greenhouse, Lever or the other ATSs? No. The Actor uses the public job-board feeds that the career sites themselves use.

Do I need proxies? No. The job-board APIs are public and the Actor keeps request rates low. A proxy option exists for edge cases.

How do I find a company's ATS slug? Open the company's careers page and click a job. The URL usually shows it: job-boards.greenhouse.io/<slug>, jobs.lever.co/<slug>, jobs.ashbyhq.com/<slug>, <tenant>.wd5.myworkdayjobs.com/<site> or jobs.smartrecruiters.com/<slug>. You can paste that URL directly.

Why is a company missing jobs I can see on its website? Some companies show jobs from several boards or use an ATS that isn't supported yet. Check which board the job links point to and add that board.

Can I get only jobs posted recently? Yes, set Posted within the last N days. For an alerting workflow, change tracking with Return only new and closed jobs is more reliable because it does not depend on posting dates.

What happens if one company fails? The other companies still run. The failed entry gets a free error row in the dataset, and the reason is also in the SUMMARY record and the run status message. A wrong slug returns "Job board not found (HTTP 404)". SmartRecruiters answers "0 jobs" for company IDs that don't exist, so an ID without jobs also gets an error row asking you to check it. If every entry fails because of the input, the run still ends as succeeded, with the error rows explaining why.

Why is remote null for some jobs? The ATS doesn't say whether those jobs are remote (common on Greenhouse boards without a workplace field and on Workday sites without a "remote type"). See "Remote jobs" above.

Is there a limit on companies per run? No hard limit. Companies are processed a few at a time; very large lists simply take longer.

Not affiliated with or endorsed by Greenhouse, Lever, Ashby, Workday, SmartRecruiters or any employer whose jobs it reads; these names are used only to describe compatibility.

This Actor only reads job postings that companies publish openly on their public career sites, through the same public endpoints those sites use. It does not log in, bypass access controls or collect personal data about candidates. Job postings may include the name of a hiring contact in rare cases; handle any personal data you receive in line with the laws that apply to you (such as GDPR). You are responsible for how you use the data and for complying with the terms of the websites you read.