Career Page Jobs Scraper - Greenhouse, Lever, Workday & ATS
Pricing
from $0.80 / 1,000 jobs
Career Page Jobs Scraper - Greenhouse, Lever, Workday & ATS
Career page jobs scraper and ATS jobs scraper: scrape job postings from Greenhouse, Lever, Ashby, Workday + 13 more ATSs, live from company domains or career-page URLs, auto-detected. Salary, remote, new-job alerts. $1/1,000 jobs.
Pricing
from $0.80 / 1,000 jobs
Rating
0.0
(0)
Developer
Yukai Lin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
What does Career Page Jobs Scraper do?
Career Page Jobs Scraper (an ATS jobs scraper) scrapes job postings from Greenhouse, Lever and 16 more applicant tracking systems: give it company domains, career pages or board URLs, and get their live open jobs from Greenhouse, Lever, Ashby, Workday and the rest (auto-detected) in one normalised format, for $1 per 1,000 jobs. Companies without a readable job board and filtered-out jobs are free.
How to scrape Greenhouse and Lever job postings
- Enter your companies, one per line:
stripe.com, a career page, a board URL such asboards.greenhouse.io/<slug>orjobs.lever.co/<slug>, orgreenhouse:<slug>. - Optional: filter by title, location, department, remote or posting date. Turn on
excludeEvergreento skip talent pools and general applications. - Click Start. Each job posting becomes one row with title, company, location, salary, posted date and
jobUrl. - Export as CSV, Excel or JSON, or turn on Only new jobs since the last run and schedule it daily. 1,000 jobs cost $1.
Why this one
- $1.00 per 1,000 jobs ($0.80 on Business and higher), no start fee. The two most used Actors that read your companies' boards live charge $1.50 (bovi) and $4.00 (memo23) per 1,000 jobs on the Free plan, plus a start fee per GB of memory (comparison, checked 2 October 2026).
- 18 ATSs, detected for you: paste
stripe.com, a career page or a board URL; Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Teamtailor, BambooHR, Rippling, Oracle Recruiting Cloud and more come back in the same columns (bovi reads 6 ATSs). - Failed and filtered items are free: a company without a readable board gets a free error row saying why, and jobs removed by your title, location, department, remote, date or optional evergreen filter cost nothing. Every job row says
evergreen: true/false; every row sayscharged: true/false. - Only new jobs since the last run, with free
closedrows, salary columns (salaryMin,salaryMax,salaryCurrency,salaryPeriod) and 6 ready-made company presets. - No login, no API key, no proxy: it reads the public job feeds the ATS vendors serve for career sites. Paste the input you already use with another ATS job scraper: its field names are mapped.
Input (copy and paste)
New engineering jobs at 32 AI companies plus two of your own, as a daily monitor:
{"companyPreset": "ai-labs","companies": ["linear.app", "jobs.lever.co/palantir"],"titleKeywords": ["engineer"],"maxJobsPerCompany": 20,"onlyNewJobs": true,"monitorName": "ai-engineering"}
Output (real result, shortened)
One job row from greenhouse:reddit ($0.001; a real run for engineering jobs at 20 AI startups, max 20 per company, returned 329 jobs for $0.33, and the same monitor run again returned 0 new jobs for $0):
{"input": "greenhouse:reddit","title": "Front End Software Engineer, Consumer Engineering","company": "Reddit","location": "Remote - United States","country": "US","workplaceType": "remote","salaryMin": 164200,"salaryMax": 229900,"salaryCurrency": "USD","salaryPeriod": "year","postedAt": "2026-09-17T17:07:34.000Z","jobUrl": "https://job-boards.greenhouse.io/reddit/jobs/8147559","ats": "greenhouse","charged": true}
All fields, ATS detection rows and error rows: Output example.
How much does it cost?
Price per 1,000 by Apify plan:
| Event | Free | Starter | Scale | Business and higher |
|---|---|---|---|---|
| Job | $1.00 | $1.00 | $0.90 | $0.80 |
| Company ATS detected (detection mode only) | $2.00 | $2.00 | $1.80 | $1.60 |
No start fee. Not charged: jobs removed by your filters, unchanged jobs with Only new jobs, duplicate jobs found on a second board, closed rows, companies without a readable job board, invalid input lines.
Features
It returns the open jobs of any list of companies, live from their own career sites. Paste career pages, company websites or job board URLs, in any mix: the Actor finds which applicant tracking system (ATS) each company uses and reads that ATS's public job board feed — the JSON, XML and RSS feeds these vendors serve so companies can show their jobs on their own websites. Every job comes back in one normalised format, whatever the ATS.
This Actor works on a known list of companies; it is not a job search engine over all employers. Give it the companies you care about, or start from a built-in company preset (AI labs, fintech, developer tools, remote-first, European tech, large enterprises on Workday).
- 🏢 18 ATSs, one schema: Greenhouse, Lever (US and EU), Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio, Breezy HR, Teamtailor, BambooHR, Rippling, Pinpoint, Gem, JazzHR, Homerun, Freshteam and Oracle Recruiting Cloud
- 🔎 ATS auto-detection: give it
stripe.comorhuggingface.co/jobsand it finds the board — from links and embeds on the page, the site's careers links, a real browser for JavaScript career pages, and finally verified guesses (stripe.com→greenhouse:stripe, accepted only when the board's company name or job texts match the domain) - 🧹 Clean, comparable fields:
location(text) pluslocations(list), ISOcountry,workplaceTypeandremote,employmentType(full-time,part-time,contract,internship…),postedAtin ISO format,jobUrl,applyUrl, and the real company name (read from the board page when the ATS feed has none) - 💰 Salary columns:
salaryMin,salaryMax,salaryCurrency,salaryPeriodfrom the ATS (Greenhouse pay-transparency ranges included, with every zone inpayRanges), or read from the pay-transparency text of the posting (salarySourcesays which), plus the same range as a yearly amount (salaryAnnualMin,salaryAnnualMax) - 🪜 Experience level:
seniority(internship,entry,mid,senior,lead,executiveor empty) withsenioritySourcesaying where it came from: the ATS's own level field, an internship employment type, or the job title - ⚡ Live, not a database copy: every run reads the boards at that moment, so a job posted an hour ago is there, and jobs that closed are gone
- 🆕 Only new jobs since the last run: for daily schedules. Unchanged jobs are not output and not charged; closed jobs get a free
closedrow - 🎯 Filters: title keywords (and exclusions), location, department, remote only, posted in the last N days, experience level (internship, entry, mid, senior, lead, executive), minimum salary, and optional excludeEvergreen. Every job row has an
evergreenflag for likely talent-pool or general-application postings; turn onexcludeEvergreento leave these rows out without paying for them. The flag is based on the title and, for vague titles only, description text. WithdescriptionFormat: "none"and the exclusion off, no description is fetched unless salary filtering needs it, so a vague title may lack description evidence. Title keywords match whole words and their common forms (engineer → Engineering; excluding intern drops Internship but keeps International Sales); use*for part of a word (*entwickler) - 🌍 Optional remote-job sources: add the Remote OK feed and the Hacker News "Who is hiring?" thread, with attribution and links back to each listing
- 🧾 ATS detection mode: one row per company with its ATS, board URL, number of open jobs, remote jobs, top departments and locations, newest posting date. It also names ATSs it can recognise but not read (iCIMS, Taleo, SuccessFactors, Jobvite, UKG, Paylocity…)
- 📋 Company presets: ready-made lists of 15 to 32 companies whose job boards were checked to work, merged with your own companies
- 🧩 Maps back to your input: every row has
inputandinputIndex; companies without a readable board get an error row saying why (not charged). The same job found on two boards is returned once - 💵 $1 per 1,000 jobs, down to $0.80 on Apify's Business plan and higher. No start fee
Supported job boards
| ATS | Paste any of these | Feed read | Description | Posted date | Salary |
|---|---|---|---|---|---|
| Greenhouse | job-boards.greenhouse.io/<slug>, boards.greenhouse.io/<slug>, embed URLs, greenhouse:<slug> | Job Board API | ✅ | ✅ first published | structured pay ranges when published, else from the posting text |
| Lever | jobs.lever.co/<slug>, jobs.eu.lever.co/<slug>, lever:<slug> | Postings API | ✅ incl. lists | ✅ | ✅ when published |
| Ashby | jobs.ashbyhq.com/<slug>, ashby:<slug> | Job Posting API | ✅ | ✅ | ✅ when published |
| Workday | <tenant>.wd5.myworkdayjobs.com/<site>, wd1.myworkdaysite.com/.../recruiting/<tenant>/<site> | the career site's JSON | ✅ (1 extra request per job) | ✅ start date | — |
| SmartRecruiters | careers.smartrecruiters.com/<Company>, smartrecruiters:<Company> | Posting API | ✅ (1 extra request per job) | ✅ | — |
| Workable | apply.workable.com/<slug>, <slug>.workable.com, workable:<slug> | widget API | ✅ | ✅ | — |
| Recruitee | <slug>.recruitee.com, recruitee:<slug> | Careers Site API | ✅ | ✅ | ✅ when published |
| Personio | <slug>.jobs.personio.de / .com, personio:<slug> | XML feed | ✅ | ✅ | — |
| Breezy HR | <slug>.breezy.hr, breezy:<slug> | /json feed | — (the feed has none) | ✅ | text |
| Teamtailor | <slug>.teamtailor.com, <slug>.na.teamtailor.com, a Teamtailor careers site on your own domain, teamtailor:<slug> | RSS feed (/jobs.rss) | ✅ | ✅ | — |
| BambooHR | <slug>.bamboohr.com/careers, bamboohr:<slug> | careers-page JSON | ✅ (1 extra request per job) | ✅ with details | text when published |
| Rippling | ats.rippling.com/<slug>/jobs, rippling:<slug> | the hosted board's JSON | ✅ (1 extra request per job) | ✅ with details | ✅ with details |
| Pinpoint | <slug>.pinpointhq.com, pinpoint:<slug> | postings.json + RSS | ✅ | ✅ | ✅ when published |
| Gem | jobs.gem.com/<slug>, gem:<slug> | Job Board API | ✅ | ✅ | from the posting text |
| JazzHR | <slug>.applytojob.com, jazzhr:<slug> | XML job feed | ✅ | ✅ creation time | — |
| Homerun | <slug>.homerun.co, homerun:<slug> | Atom job feed | ✅ | — (last update only) | text when published |
| Freshteam | <slug>.freshteam.com/jobs, freshteam:<slug> | careers widget JSON | ✅ | ✅ | — |
| Oracle Recruiting Cloud | <tenant>.fa[.<region>].oraclecloud.com/hcmUI/CandidateExperience/<lang>/sites/<site> (career site or job URL), oracle:<host>/<site> (e.g. oracle:jpmc.fa.oraclecloud.com/CX_1001) | the career site's REST API (recruitingCEJobRequisitions) | ✅ (1 extra request per job) | ✅ | text when published (with details) |
A company website or career page (e.g. linear.app, webull.com, functionhealth.com) works too: the board is detected. For any ATS, the salary columns are also filled from the posting's own pay-range text when the ATS has no salary fields (salarySource: "description"). Greenhouse boards that publish pay ranges (pay transparency) fill the salary columns from those structured ranges instead (salarySource: "ats", salarySourceDetail: "greenhouse_pay_transparency", every range in payRanges).
Company presets
Don't know where to start? Pick a Company list preset. Every board in these lists returned open jobs when the lists were checked (3 October 2026); boards that answered "not found", had no jobs or belonged to another company were left out. A preset is merged with Companies (a board in both is read once), and a board that closes later only gets a free error row.
| Preset | Companies | Examples |
|---|---|---|
ai-labs | 32 | OpenAI, Anthropic, Perplexity, Cohere, ElevenLabs, Hugging Face, Scale AI, Databricks, Cursor, Harvey, Lovable |
fintech | 20 | Stripe, Coinbase, Ramp, Brex, Chime, Affirm, Robinhood, Adyen, Monzo, N26, Toast |
developer-tools | 28 | Cloudflare, Datadog, GitLab, Vercel, Supabase, Replit, Linear, Figma, MongoDB, Sentry, Grafana Labs |
remote-first | 15 | GitLab, Zapier, Automattic, PostHog, Canonical, DuckDuckGo, Wikimedia, Mozilla, Oyster |
european-tech | 20 | N26, Monzo, Adyen, Spotify, Deliveroo, Celonis, Doctolib, HelloFresh, Wolt, DeepL, Synthesia |
enterprise-workday | 21 | NVIDIA, Salesforce, Adobe, Intel, Mastercard, Cisco, Capital One, Pfizer, Boeing, Disney, PayPal |
The enterprise boards have hundreds to thousands of open jobs each: set Max jobs per company or title filters before running that preset.
Extra sources (option Extra sources, same price per job, same filters):
| Source | What you get | Terms we follow |
|---|---|---|
| Remote OK | the latest remote jobs of the public Remote OK API (99 jobs on 30 September 2026) | Remote OK asks for a link back to the listing and to name Remote OK as the source: every row has jobUrl on remoteok.com and an attribution line |
| Hacker News "Who is hiring?" | top-level posts of the latest monthly thread, via the official HN API (300 posts in the September 2026 thread) | jobUrl links to the HN comment; email addresses in posts are removed |
Who is it for?
- Job boards and aggregators: fill a niche board with fresh jobs from a list of companies every day, with only-new-jobs monitoring
- Recruiters and talent teams: watch competitors' and target companies' openings
- Sales and market research: hiring signals — who is hiring for which teams and where, which ATS a company uses
- Compensation research: published pay ranges by title and company, in separate min/max/currency/period columns
- Job seekers and career coaches: one daily list of matching jobs from dream companies
- AI agents: "find open ML engineer jobs in Berlin at these 50 startups"
Cost control and price comparison
For comparison (checked 2 October 2026, Apify Store prices on the Free plan; details in Switching from another ATS job scraper): other ATS job scrapers charge $0.0015 per job (bovi/greenhouse-lever-ashby-job-scraper), $0.002 (fantastic-jobs Greenhouse, Ashby and Workday APIs), $0.004 (jobo.world ATS scrapers; memo23/career-site-ats-jobs-api) and $0.012 (fantastic-jobs/career-site-job-listing-api, a database of jobs collected in advance rather than a live read of your companies).
Control your cost
- What is charged: each job returned (jobs mode) or each company whose ATS was identified (detection mode).
- Max jobs caps the whole run (default 10,000 when you call the API without it: at most $10 on the Free plan). Max jobs per company caps each company.
- Filters are applied before charging: title keywords, location, department, remote only and posted-in-the-last-N-days all reduce what you pay.
- Only new jobs makes daily schedules cheap: after the first run, you pay only for jobs that appeared since the previous run.
- At the start, the run logs its worst case (e.g.
Plan: 400 jobs × $0.001 = at most $0.4) and warns when that is more than your maximum charge per run. - When the maximum charge per run is reached, the run stops, keeps everything found so far, and says so. The
SUMMARYrecord then hasstatus: "LIMIT_REACHED"andnotProcessed(up to 100 companies not processed or not finished). With Only new jobs, jobs that were not delivered because of a limit are reported as new again on the next run.
Worked example (real runs, 30 September 2026, Free plan prices):
| Run | Setting | Jobs returned | Cost |
|---|---|---|---|
| Engineering jobs at 20 AI startups (OpenAI, Anthropic, Perplexity, Cohere…) | titles engineer, developer, scientist; max 20 per company; only new jobs, first run | 329 | $0.33 |
| Same monitor, run again 10 minutes later | only jobs posted since the previous run | 0 | $0 |
| Remote jobs posted in the last 24 hours at 15 Greenhouse companies | remote only, posted in the last 1 day | 35 | $0.035 |
| Which ATS do 17 companies use? | detection mode | 16 detected, 1 not found (free) | $0.032 |
Without the title filter and caps, the same 20 AI startups had about 3,900 open jobs (about $3.90 for a full first run), so the filter and Max jobs per company are what keep the first run at $0.33. After that you pay only for new postings.
Switching from another ATS job scraper
If you already run another Actor that reads a list of companies' job boards, you can paste your existing input as is. This Actor also accepts the field names those Actors use and maps them to its own; the run log lists every mapping and every field it could not use.
Comparison with the two most used Actors of the same kind (live read of the companies you give), Apify Store data checked on 2 October 2026:
| This Actor | bovi/greenhouse-lever-ashby-job-scraper | memo23/career-site-ats-jobs-api | |
|---|---|---|---|
| Price per 1,000 jobs, Free plan | $1.00 | $1.50 | $4.00 |
| Price per 1,000 jobs, lowest plan tier price | $0.80 | $1.43 | $2.50 |
| Start fee | none | $0.00005 per GB of memory | $0.03 per GB of memory |
| ATSs read | 18 (incl. Workday, Workable, Teamtailor, BambooHR, Rippling, Oracle Recruiting Cloud) | 6 (Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters, Personio) | 116 (incl. iCIMS, Taleo, SuccessFactors) |
| Companies without a readable board | free error row in the dataset, with the reason | listed in failedTargets | listed in INPUT-STATUS.csv |
| Only new jobs between runs | yes, plus free closed rows | yes (new and closed) | yes (new and updated) |
| Company presets | 6 lists | 4 lists | no |
| Input | board URLs, ats:slug, or a company website / domain (board detected) | {ats, company} slugs (ATS optional) | board URLs, bare company names, or a spreadsheet of links |
| Extras | salary from ATS and posting text, Remote OK and HN feeds, ATS detection mode | hiring-signal report mode | contact emails (paid add-on), application questions, translation |
Choose the other Actor when you need what it has and this one does not: enterprise ATSs such as iCIMS, Taleo or SuccessFactors, bare company names without a domain, or a hiring-signal report.
Fields read from other Actors' inputs (your own field always wins when both are set):
| Their field | Read here as |
|---|---|
startUrls (strings or { "url": … }), urls, organizations, domainFilter, organizationSearch, companies_include | companies |
companies as { "ats": "greenhouse", "company": "stripe" } | companies line greenhouse:stripe |
greenhouseBoards, leverCompanies, ashbyOrgs, smartrecruitersCompanies | companies lines greenhouse:…, lever:…, ashby:…, smartrecruiters:… |
presetLists (ai-ml, devtools, fintech) | companyPreset (ai-labs, developer-tools, fintech) |
titleKeyword, titleSearch, jobTitles, queries / titleExclusionSearch | titleKeywords / excludeTitleKeywords |
locationKeyword, location, locations, locationSearch (city part) / department | locationKeywords / departments |
postedAfter, datePostedAfter, posted_after, postedOnOrAfter (a date), timeRange (24h, 7d) | postedWithinDays |
maxItemsTotal, maxItems, maxResults, limit | maxJobs (whole run; set maxJobsPerCompany for a per-company cap) |
onlyNewSinceLastRun, onlyNewOrUpdated / stateKey | onlyNewJobs / monitorName |
includeDescriptions: false, includeDescription: false / descriptionType | descriptionFormat |
proxy | proxyConfiguration |
Bare company names ("notion", "Stripe") are not looked up: they return a free invalid_input row, so give the domain (notion.so) or the board URL instead. Description keyword search (keywords, descriptionSearch) is not supported and is reported in the log.
Example: this input, written for another Actor, runs here unchanged:
{"startUrls": ["https://boards.greenhouse.io/lattice", "https://jobs.ashbyhq.com/ramp"],"companies": [{ "ats": "lever", "company": "spotify" }],"titleKeyword": "engineer","location": "remote","postedAfter": "2026-09-15","maxItems": 200,"onlyNewSinceLastRun": true}
The run log lists each mapping ("startUrls" read as "companies", "titleKeyword" read as "titleKeywords", …). The run reads the three boards, keeps engineering jobs whose location contains "remote" and that were posted since 15 September (counted in whole days), stops at 200 jobs in total, and remembers them for the next run.
Database search Actors (for example fantastic-jobs/career-site-job-listing-api, $12.00 per 1,000 on the Free plan, or jobo.world/ats-jobs-api, $4.00) search jobs collected in advance across all employers. This Actor does not search all employers; if you used their domain filter for a known list of companies, domainFilter is read as companies and the jobs are read live from each company's board.
How to use it
- Enter your companies, one per line: job board URLs, career pages, websites or
ats:slug. Or pick a Company list preset (alone or together with your companies). - Optional: set filters (title, location, department, remote, posted in the last N days, experience level, minimum salary) and Max jobs per company.
- Optional: add Extra sources (Remote OK, Hacker News "Who is hiring?").
- Optional: turn on Only new jobs since the last run and schedule the Actor daily.
- Click Start and export as CSV, Excel or JSON, or call it from the API. The Jobs (overview) table has the columns most people need; Jobs (all fields) has everything.
Input example
New engineering jobs at 32 AI companies plus two of your own, as a daily monitor:
{"companyPreset": "ai-labs","companies": ["linear.app", "jobs.lever.co/palantir"],"titleKeywords": ["engineer"],"maxJobsPerCompany": 20,"onlyNewJobs": true,"monitorName": "ai-engineering"}
Any mix of boards, websites and filters:
{"companies": ["https://job-boards.greenhouse.io/airbnb","jobs.lever.co/palantir","https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite","https://career.teamtailor.com","ats.rippling.com/chess/jobs","linear.app","smartrecruiters:BoschGroup"],"titleKeywords": ["engineer", "data scientist"],"excludeTitleKeywords": ["intern"],"locationKeywords": ["US", "Remote"],"postedWithinDays": 14,"maxJobsPerCompany": 100,"descriptionFormat": "text"}
Output example (jobs mode)
A real result from greenhouse:reddit (description shortened), captured before structured pay was read. The salary was read from the posting's pay-range text; Reddit now publishes Greenhouse pay ranges for most jobs, so such jobs come with salarySource: "ats", salarySourceDetail: "greenhouse_pay_transparency" and payRanges:
{"input": "greenhouse:reddit","inputIndex": 5,"success": true,"jobKey": "greenhouse:reddit:8147559","jobId": "8147559","title": "Front End Software Engineer, Consumer Engineering","company": "Reddit","department": "Consumer","team": null,"location": "Remote - United States","locations": ["Remote - United States"],"country": "US","workplaceType": "remote","remote": true,"employmentType": null,"employmentTypeText": null,"seniority": null,"senioritySource": null,"seniorityText": null,"salaryMin": 164200,"salaryMax": 229900,"salaryCurrency": "USD","salaryPeriod": "year","salaryAnnualMin": 164200,"salaryAnnualMax": 229900,"salaryText": "$164,200—$229,900 USD","salarySource": "description","postedAt": "2026-09-17T17:07:34.000Z","postedAtApproximate": false,"updatedAt": "2026-09-17T17:07:34.000Z","jobUrl": "https://job-boards.greenhouse.io/reddit/jobs/8147559","applyUrl": "https://job-boards.greenhouse.io/reddit/jobs/8147559","requisitionId": "Pooled","descriptionText": "Reddit is a community of communities. It’s built on shared interests, passion, and trust, and is home to the most open and authentic conversations on …","source": "ats","ats": "greenhouse","atsSlug": "reddit","boardUrl": "https://job-boards.greenhouse.io/reddit","detectionMethod": "input","charged": true,"scrapedAt": "2026-09-30T04:52:29.128Z"}
Fields are the same for every ATS; a field the ATS does not publish is null. jobKey (ats:slug:jobId) is unique across boards and stable between runs. workplaceType is remote, hybrid, onsite or null; employmentType is the normalised value and employmentTypeText the ATS's own wording. postedAtApproximate is true when the date comes from Workday's "Posted N Days Ago". detectionMethod tells how the board was found: input, career-page, careers-link, career-page-browser, slug-guess or source.
A row from the Hacker News source (other fields as above):
{ "input": "source:hackernews", "jobKey": "hackernews:49524580", "title": "Lead Product Manager, Security", "company": "Wikimedia Foundation", "location": "REMOTE (US + 18 countries)", "workplaceType": "remote", "employmentType": "full-time", "postedAt": "2026-09-01T16:52:15.000Z", "jobUrl": "https://news.ycombinator.com/item?id=49524580", "source": "hackernews", "attribution": "Job post from the Hacker News \"Ask HN: Who is hiring?\" thread (https://news.ycombinator.com), via the official HN API. Link back to jobUrl when you republish it." }
With Only new jobs, rows also have changeType: "new" and firstSeenAt, and jobs that disappeared get a free row with changeType: "closed", firstSeenAt and closedAt.
Output example (ATS detection mode)
Real result for webull.com (lists shortened):
{"input": "webull.com","success": true,"company": "Webull","companyWebsite": "https://webull.com","ats": "rippling","atsSupported": true,"atsSlug": "webull","boardUrl": "https://ats.rippling.com/webull/jobs","jobCount": 29,"remoteJobs": 0,"topDepartments": [{ "name": "Finance", "jobs": 8 }, { "name": "Institutional", "jobs": 4 }, { "name": "Clearing Operations", "jobs": 3 }],"topLocations": [{ "name": "Saint Petersburg, FL", "jobs": 19 }, { "name": "New York, NY", "jobs": 9 }, { "name": "Toronto, Canada", "jobs": 1 }],"detectionMethod": "careers-link","foundOn": "https://www.webull.com/careers","charged": true}
In the same run, stripe.com → greenhouse:stripe (711 jobs), functionhealth.com → gem:function-health (33), ioet.com → teamtailor:ioet.na (5), youlend.com → pinpoint:youlend (25) and getflowpath.com → freshteam:getflowpath (3).
A company without a readable job board
Real output for netflix.com (its career site is not on a supported ATS; pagesTried shortened). Not charged:
{"input": "netflix.com","success": false,"errorType": "not_found","error": "no supported ATS job board found on https://netflix.com or its career links (supported: greenhouse, lever, ashby, workday, smartrecruiters, workable, recruitee, personio, breezy, teamtailor, bamboohr, rippling, pinpoint, gem, jazzhr, homerun, freshteam). Tip: paste the job board URL instead (not charged)","pagesTried": [{ "url": "https://netflix.com", "via": "direct" }, { "url": "https://jobs.netflix.com/jobs", "via": "browser" }, { "url": "greenhouse:netflix", "result": "no match" }],"charged": false}
errorType is unsupported when the company uses an ATS without a public feed (listed in atsDetected), not_found when no board was found or a board URL does not exist, no_jobs when the board was read but has no open jobs right now (or the company id is wrong: SmartRecruiters ids are case-sensitive), network/timeout/blocked when a page or feed could not be loaded (rate limits and server errors are retried with backoff first), and invalid_input for lines that are not a company (or an unknown preset name).
The SUMMARY record (key-value store) has status (SUCCESS, PARTIAL_RESULTS, FAILED, NO_RESULTS, LIMIT_REACHED), totals (including duplicatesSkipped), and perCompany: ATS, slug, company, jobsFound (open jobs on the board) and jobsOutput (after filters) for every company.
Integrations
- Schedules: run daily with Only new jobs for a new-jobs feed.
- API and webhooks: start runs and read the dataset from any language; use a webhook to get notified when a run finishes.
- Exports: CSV, Excel, JSON, XML and HTML from the dataset (the overview view gives a flat table).
- Apify integrations: send results to Google Sheets, Slack, Zapier, Make, n8n and others from the Integrations tab.
- AI agents (MCP): connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/ats-career-site-jobs) to Claude, Cursor or any MCP client, then ask e.g. "List open data engineering jobs in Europe at linear.app, notion.so and ramp.com, posted in the last two weeks."
{ "companies": ["linear.app", "notion.so", "ramp.com"], "titleKeywords": ["data"], "locationKeywords": ["Europe", "London", "Berlin"], "postedWithinDays": 14 }
Tips and limitations
- Pasting the board URL is the most reliable input. Detection from a website works for most startups and scale-ups; big companies often use career sites on ATSs without a public feed (they get an
unsupportedornot_foundrow, free). - Guessed boards (
detectionMethod: "slug-guess") are accepted only when the board has open jobs, its newest job is less than a year old, and its company name or job texts match the domain. Turn Guess the board off in Advanced settings if you only want boards linked from the website. Guesses are probed in parallel with a short timeout (12 s each, 60 s per company in total), so a slow job board cannot hold up a run. - Oracle Recruiting Cloud is read newest first, at most 5,000 jobs per career site (25 pages of 200); a bigger site gets a note in
notes. The API has no company name: it comes from the career site's name when it has one ("JPMC Candidate Experience page" → "JPMC"), else the tenant label (ejov→ "Ejov"). - Workday lists at most 2,000 jobs per search. For bigger employers, a single title keyword is sent to Workday as a search, so you still reach the matching jobs.
- Extra requests per job: Workday, SmartRecruiters, Rippling, BambooHR and Oracle Recruiting Cloud need one request per job for descriptions; choose Job description: None for faster runs. Rippling and BambooHR then have no posting date (and Rippling no salary) unless Posted in the last N days is set.
- Homerun feeds have no publication date (only
updatedAt), so Posted in the last N days drops Homerun jobs. JazzHR dates are the job's creation time. Freshteam feeds have no employment type. - Salary from the posting text is read only when a currency and a plausible range are written (e.g.
$164,200—$229,900); single amounts and vague text are ignored. In a real run on 92 software engineer jobs from 10 companies, 49 salaries came from the ATS and 35 from the posting text. - Experience level (
seniority) is derived, never invented. In this order: (1) the ATS's own level field where it has one (Personioseniority, BambooHR minimum experience, JazzHR experience; the raw value is inseniorityText) when it names one level; (2) an internship or apprenticeship employment type; (3) words in the title: Intern/Werkstudent →internship; Junior/Jr/Graduate/New Grad/Trainee or "Engineer I" →entry; Mid-level/Intermediate or "Engineer II" →mid; Senior/Sr or "Engineer III" →senior; Lead/Staff Engineer/Principal/Supervisor/Engineering Manager →lead; Director/Head of/VP/Chief/President →executive. Functional "manager" titles (Product, Project, Account, Marketing Manager…) do not count as people managers. (4) a vague ATS value ("Experienced") →mid, only when the title says nothing. Otherwiseseniorityis empty: many titles ("Software Engineer") name no level, so the filter drops them unless Also keep jobs without a known experience level is on. - Minimum salary compares only jobs that state a salary (ATS pay fields, or a range in the posting text: descriptions are read while this filter is on). Periods are compared as yearly amounts (hour × 2080, day × 260, week × 52, month × 12). Other currencies are converted with fixed approximate rates (about 45 currencies, rounded autumn-2026 rates, can be some percent off) for the comparison only; turn Compare salaries in other currencies off to compare one currency only. By default a range passes when its top reaches your minimum (choose Salary must: start at or above the minimum for the strict reading). Jobs without a comparable salary are kept by default (
SUMMARY.jobsKeptWithoutComparableSalarycounts them). - Greenhouse pay ranges: when a job has several ranges (location zones such as "Zone 1 (New York…)", or two currencies),
salaryMin/salaryMaxspan the ranges in the first range's currency andpayRangeslists each one (title,min,max,currency,interval). A range without a stated period is read as yearly from 10,000 and hourly up to 200. - Career page requests from: Our second server only sends career pages and job board API requests through our second server (another IP), for boards that refuse data-center networks. Workday searches are POST requests and still go from Apify's network. SUMMARY shows
requestsViaSecondServer. - Hacker News titles and locations are read from the first line of each post (
Company | Role | Location | …); posts that do not follow that pattern use their first line or the first role mentioned. Only the latest monthly thread is read. - Remote jobs only keeps jobs whose workplace type is remote and jobs whose location list names a remote option (for example
US - Remote; Seattle);workplaceTypeandremoteshow what the ATS says about the job's main arrangement, so a multi-location job can behybridand still pass. - Max jobs is shared by the whole run. A company read after it is used up delivers nothing, is not charged, and is listed in
SUMMARY.notProcessed; raise Max jobs to get it. A company that has open jobs but none matching your filters gets no rows (free):SUMMARY.perCompany[].notesaysno job matched your filters. - Websites on a subdomain (
about.gitlab.com/jobs,careers.acme.com) are matched to the company name for board guesses, and links to the ATS vendors' own marketing pages are not taken for a company board. - SmartRecruiters company ids are case-sensitive (
BoschGroup); an unknown id returns 0 jobs. - Only new jobs remembers jobs per monitor name. Use a different monitor name when you change the company list or filters.
- Job boards change their feeds from time to time; if a board stops working, open an issue with the URL.
Responsible use
The Actor reads only public job postings from the job feeds that ATS vendors provide for publishing jobs on career sites and job boards, and from public job feeds whose terms allow reuse with attribution. It does not log in, does not collect applicant data and does not extract recruiters' personal contact details (email addresses in Hacker News posts are removed). If you republish jobs, link to the original posting (jobUrl), keep the attribution of Remote OK and Hacker News rows, and follow the rules of the site where you publish them.
FAQ
Does the Actor collect usage data? The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.
How fresh are the jobs? As fresh as the company's board: each run reads it live.
Can it search all companies for a job title? No. It reads the boards of the companies you give it (or of a company preset) live; it is not a search engine over every employer. Use title, location and remote filters to narrow those companies' jobs.
Why did I get fewer jobs than the board shows? Check your filters, Max jobs per company and Max jobs, duplicates removed across boards (SUMMARY.duplicatesSkipped), and SUMMARY.perCompany[].jobsFound.
How is the experience level decided? Is it AI? No AI and no guessing: the ATS's own level field when it has one, an internship employment type, or level words in the title (see Tips and limitations). senioritySource (ats, employment_type, title) says which; jobs whose title names no level have an empty seniority. Tick Also keep jobs without a known experience level to keep them while the filter is on.
How does the minimum salary filter treat jobs without a salary? It keeps them by default, because most boards publish pay only where the law requires it. Turn Keep jobs that state no salary off to get only jobs with a stated salary that reaches your minimum. Jobs removed by the filter are not charged.
Can I filter by salary in euros or per hour? Yes: set Minimum salary currency (e.g. EUR) and Minimum salary period (e.g. hour). Other currencies and periods are converted for the comparison only (approximate fixed exchange rates); the job's own salary fields stay as published, and salaryAnnualMin/salaryAnnualMax give the yearly amount in the job's own currency.
Why is company different from the slug? The name comes from the ATS feed, or from the board page's title when the feed has none (Lever, Ashby, Gem, BambooHR, Freshteam): jobs.lever.co/palantir gives "Palantir Technologies". Workday feeds have no company name, so the tenant name is used ("Nvidia").
Can I run it on a schedule? Yes. Turn on Only new jobs since the last run, set a monitor name, and create a daily schedule in Apify Console; each run returns only the jobs posted since the previous one.
Why is there no row for a company? Either it has open jobs but none matched your filters (free, see SUMMARY.perCompany[].note), or it was reached after Max jobs was used up (see SUMMARY.notProcessed), or no readable board was found: that gives a free error row with charged: false and the reason.
What are the limits? Max jobs caps the whole run (default 10,000, up to 1,000,000) and Max jobs per company caps each company; Apify's Maximum cost per run stops the run cleanly, keeping what was found. Workday lists at most 2,000 jobs per search (a single title keyword is sent as a search, so you still reach the matching jobs).
How fast is it? Several companies are read at the same time (5 by default, up to 20 with Companies in parallel). Workday, SmartRecruiters, Rippling and BambooHR need one extra request per job for descriptions, so choose Job description: None for the fastest runs. A board guess never holds up a run for more than 60 seconds per company.
Is it legal to scrape job postings? The Actor reads only public job postings, from the job feeds ATS vendors provide for publishing jobs on career sites, plus the Remote OK and Hacker News feeds with attribution. It does not log in, collect applicant data or extract recruiters' contact details. See Responsible use before republishing jobs. This is not legal advice.
Does it work with the API, webhooks, Make, n8n or Zapier? Yes. Start runs from the Apify API, a schedule or a webhook, send results to Google Sheets, Slack, Make, n8n or Zapier from the Integrations tab, and use it from AI agents through Apify's MCP server (details and example).
Which ATSs can't it read? iCIMS, Taleo, SuccessFactors, Jobvite, UKG, Paylocity, ADP, Paycom, Dayforce, Zoho Recruit, HiBob, Comeet, JOIN and a few others are recognised (detection mode tells you which one a company uses) but not read, because they publish no public job feed we can use.
My company's ATS is not supported. Detection mode tells you which ATS it uses; open an issue and it may be added.
Found this useful? A short review on the Store helps other users find it.