Company Career Page Jobs Scraper
Pricing
from $1.50 / 1,000 job listing returneds
Company Career Page Jobs Scraper
Give it company domains or careers URLs: it detects the ATS (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio) and returns every open job in one normalized schema with salary, remote flag and dates, plus an only-new-jobs mode for monitoring.
Pricing
from $1.50 / 1,000 job listing returneds
Rating
0.0
(0)
Developer
Juddroid
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Paste company domains or careers page URLs and get every open job in one clean, normalized table, whatever applicant tracking system (ATS) the company uses.
What does Company Career Page Jobs Scraper do?
You give it a list of companies: a domain like linear.app, a careers page like https://acme.com/careers, or a direct job board URL. For each company it finds the ATS behind the careers page (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee or Personio) and reads the jobs from that ATS's public job-board feed. Every job comes back in the same schema: title, department, locations, remote/hybrid/on-site, employment type, salary range, posted date, job and apply URLs, and the description. Turn on Only new jobs and schedule it, and each run returns just the jobs that appeared since the last run, with a webhook ping when there is something new.
Why use it
- One schema across eight ATSs. No more separate scrapers per ATS with different field names. A Workday job and a Greenhouse job look the same in your spreadsheet, CRM or database.
- You don't need to know the ATS. Give it a domain and it works out where the jobs live. The detection is explained per company (
detectionMethodplus the evidence in the run summary), so you can see why a board was picked. - Guards against wrong boards. A domain guess like
example.com→ boardexampleis only accepted when the board's website matches the domain or the job ads mention it. Lookalike boards are rejected and listed in the notes. - Salary where it exists. Structured pay ranges from Ashby, Lever and Recruitee (and Greenhouse pay ranges when a company publishes them) are used first. Otherwise US/EU pay-transparency sentences ("The base salary range is $136,000 USD - $212,750 USD") are parsed conservatively. Stipends, bonuses and funding amounts are ignored.
- Built for monitoring. Only-new-jobs mode keeps the job IDs per company between runs. It reports new and removed jobs per company and can POST a summary to Slack or any webhook.
- Cheap and fair. You pay per job row only. Companies without an ATS, empty boards, failures and filtered-out jobs are free.
- A hiring signal for outbound. A company that is hiring for sales, engineering or a new region is a strong buying signal. Feed the companies with new jobs straight into our B2B Outreach Route Finder Actor to get the best contact route for each one.
Supported ATSs
| ATS | Example input | How jobs are read | Notes |
|---|---|---|---|
| Greenhouse | vercel.com, boards.greenhouse.io/vercel, job-boards.greenhouse.io/vercel | Public board API, one request per company | Descriptions included; pay ranges when the company publishes them |
| Lever | spotify.com, jobs.lever.co/zoox, jobs.eu.lever.co/x | Public postings API, one request | Structured salaryRange when present; workplace type |
| Ashby | linear.app, jobs.ashbyhq.com/openai | Public job-board API with compensation | Structured compensation; company website used for verification |
| Workday | https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite, any *.myworkdayjobs.com or myworkdaysite.com URL | Public CXS JSON API, 20 jobs per page | Descriptions need one request per job (toggle Include job description) |
| SmartRecruiters | jobs.smartrecruiters.com/Ubisoft2 | Public postings API, 100 jobs per page | Descriptions need one request per job |
| Workable | huggingface.co, apply.workable.com/huggingface | Public widget and board APIs | Descriptions included |
| Recruitee | channable.recruitee.com, or a Recruitee careers site on the company's own domain (https://jobs.channable.com) | Public offers API | Structured salary when published |
| Personio | ottonova.jobs.personio.de, ottonova.de | Public XML job feed | German-only ads are filled from the German feed |
How ATS detection works
For each input the Actor tries the cheapest method first and records which one worked in detectionMethod:
direct_ats_url: you gave a board, job or API URL of a supported ATS. It is parsed directly, including the Workday tenant, data center (wd1...wd12) and site.careers_page_scan(for careers URLs): the page you gave is scanned for ATS links, iframes, embed scripts and?gh_jid=/?ashby_jid=job links.domain_slug_guess: the company name is derived from the domain (linear.app→linear, plus a hyphen-free variant and a variant without prefixes likeget/tryor suffixes likehq/app). It is tried on Greenhouse, Lever and Ashby. A guess is accepted only if the board has jobs and passes a sanity check: the board's own website is the domain, or the job ads mention the domain. When only the board's name matches, the guess is accepted only if the company homepage confirms that name and does not redirect elsewhere.homepage_scan/careers_page_scan: the homepage and likely careers pages (links containing careers, jobs, join us, karriere and so on, plus/careers,/jobs,/company/careers) are scanned for ATS links, embeds and job-ID parameters. Up to 6 pages per company are scanned. Recruitee careers sites on a custom domain and Personio widgets are recognized too.
Example from a real run: ramp.network → the Ashby board ramp was rejected because it belongs to ramp.com, and the company's own Greenhouse board rampnetwork was then found on its /join-us page. For example.com, the unrelated Greenhouse board example ("Democorp") was rejected.
What data you get
One row per job (type: "job"), plus one uncharged status row per company where no jobs could be returned (type: "company_status").
| Field | Description |
|---|---|
type | job or company_status |
company, companyDomain | Company name (from the ATS when available) and registrable domain |
ats, atsBoardUrl | greenhouse, lever, ashby, workday, smartrecruiters, workable, recruitee or personio, and the board URL |
detectionMethod | direct_ats_url, domain_slug_guess, careers_page_scan or homepage_scan |
jobId | The ATS job ID (stable between runs, used for only-new-jobs mode) |
title, department, team | As published on the board |
locations[] | All locations of the job |
isRemote, workplaceType | remote, hybrid, onsite or null when the ATS doesn't say |
employmentType | full_time, part_time, contract, internship, temporary, permanent... |
salary | { min, max, currency, interval, raw, source }. interval is year, month, week, day or hour. source is ats (structured field) or description (parsed pay-transparency text). null when no pay is published |
postedAt, updatedAt | ISO timestamps (Workday without descriptions: day precision from "Posted 3 Days Ago") |
jobUrl, applyUrl | Job page and application link |
descriptionText, descriptionHtml | Plain-text description (default on); HTML only when Also include description HTML is on |
isNew | true in only-new-jobs mode, null otherwise |
input, scrapedAt | The input line this row came from, and the time of the scrape |
status, message, notes | Status rows only: no_ats_detected, no_jobs or failed, with an explanation and rejected guesses |
The run's key-value store also has a SUMMARY record with one entry per company: ATS, board, detection method and evidence, jobs on the board, jobs matched and pushed, newJobsCount and removedJobsCount.
How to use
- Paste your companies into Companies, one per line: domains, careers pages or ATS board URLs.
- Set Max jobs per company. It caps both the result size and the cost per company.
- Optionally add filters: title keywords, excluded title keywords, locations, remote only, departments, posted within N days. Filtered-out jobs are not charged.
- Keep Include job description on for full text and salary parsing. Turn it off to make Workday and SmartRecruiters boards much faster.
- Click Start, then export the Jobs view as CSV, Excel or JSON.
{"companies": ["vercel.com","https://linear.app/careers","jobs.lever.co/zoox","https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite","huggingface.co","ottonova.de"],"maxJobsPerCompany": 50,"titleKeywords": ["engineer", "sales"],"excludeTitleKeywords": ["intern"],"locations": ["United States", "Remote"],"postedWithinDays": 30,"includeDescription": true,"onlyNewJobs": false}
Output example
Real rows from a local test run (descriptions trimmed):
{"type": "job","company": "Vercel","companyDomain": "vercel.com","ats": "greenhouse","atsBoardUrl": "https://job-boards.greenhouse.io/vercel","jobId": "5999792004","title": "Account Executive, Majors","department": "Account Executive","team": null,"locations": ["Hybrid - London", "London, England, United Kingdom"],"isRemote": false,"workplaceType": "hybrid","employmentType": null,"salary": {"min": 200000, "max": 270000, "currency": "GBP", "interval": "year","raw": "The London based pay range for this role is 200,000 - 270,000 GBP OTE.","source": "description"},"postedAt": "2026-05-21T13:26:09.000Z","updatedAt": "2026-09-24T21:12:05.000Z","jobUrl": "https://job-boards.greenhouse.io/vercel/jobs/5999792004","applyUrl": "https://boards.greenhouse.io/embed/job_app?for=vercel&token=5999792004","descriptionText": "About Vercel:\n\nVercel is the agentic infrastructure company, freeing people and agents to ship what's next...","isNew": null,"detectionMethod": "domain_slug_guess","input": "vercel.com","scrapedAt": "2026-10-16T10:37:23.997Z"}
{"type": "job","company": "Channable","companyDomain": "channable.com","ats": "recruitee","atsBoardUrl": "https://jobs.channable.com/","jobId": "2773400","title": "Talent Acquisition Partner","department": "Operations","locations": ["Utrecht, Netherlands"],"isRemote": false,"workplaceType": "hybrid","employmentType": "full_time","salary": { "min": 4250, "max": 5000, "currency": "EUR", "interval": "month", "raw": null, "source": "ats" },"postedAt": "2026-10-08T08:03:01.000Z","jobUrl": "https://jobs.channable.com/o/talent-acquisition-partner","applyUrl": "https://jobs.channable.com/o/talent-acquisition-partner/c/new","detectionMethod": "careers_page_scan"}
A company without a detectable ATS gets a free status row:
{"type": "company_status","status": "no_ats_detected","message": "No supported ATS found via domain guesses or 5 scanned page(s)","input": "example.com","companyDomain": "example.com","notes": ["Rejected greenhouse board \"example\": nothing links board \"Democorp\" to example.com"]}
Monitoring new jobs (schedule + webhook)
- Turn on Only new jobs since the last run and pick a Snapshot store name for this watchlist, for example
sales-targets-q4. - Run it once. The first run returns every current job: this is your baseline.
- Add a Schedule in Apify Console (daily or weekly) with the same input.
- Optional: paste a Slack incoming-webhook URL (or a Zapier/Make/n8n URL) into Webhook URL for new jobs. After each run with at least one new job, the Actor POSTs a JSON summary. It includes a Slack-ready
textline per company,totals, and up to 50 new jobs per company with title, URL, locations and salary.
Each later run outputs and charges only jobs whose ID was not seen before. The SUMMARY record and the run's status message also report removedJobsCount per company (jobs that disappeared since the previous run, often a sign the role was filled). Use separate store names for separate watchlists. Jobs that were new but not delivered because of the cap or a spending limit are kept unseen, so they show up in the next run.
Pricing
$0.0015 per job row (event job-listing), which is $1.50 per 1,000 jobs. Per-1,000-job prices for career-site job data commonly range from about $2 to $12, so this sits at the low end.
| Run | Jobs returned | Cost |
|---|---|---|
| 10 companies × 50 jobs | 500 | $0.75 |
| 100 companies × 30 jobs | 3,000 | $4.50 |
| 1,000 companies, 20 jobs each after filters | 20,000 | $30.00 |
| Weekly monitoring of 200 companies, about 3 new jobs each | 600 per week | $0.90 per week (after the baseline run) |
Not charged: company status rows (no ATS detected, empty board, failed or invalid input), jobs removed by your filters, jobs already seen in only-new-jobs mode, duplicate inputs, and the webhook. Max jobs per company and the filters let you control spend precisely. If you set a maximum cost per run, the Actor stops cleanly when it is reached and records that in the summary.
Integrations / scheduling
- Schedules: run daily or weekly with only-new-jobs mode for a hiring-signal feed.
- Webhooks: the built-in webhook posts new jobs to Slack, Zapier, Make or n8n. Apify's own run webhooks can trigger any downstream job when a run finishes.
- API: start runs and read the dataset from any language with the Apify API or the JavaScript and Python clients. Use
?view=overviewfor the compact table. - MCP and AI agents: the Actor can be called as a tool through the Apify MCP server, so an agent can ask "which of these 50 companies are hiring data engineers?"
- B2B Outreach Route Finder: pass
companyDomainfrom companies with new relevant jobs to that Actor to find the best sales inbox, form or phone line for each.
FAQ & limitations
Who is this for? Recruiters and sourcers tracking target employers, sales teams using hiring as a buying signal, job boards and aggregators that need clean feeds from company boards, and market researchers following hiring trends by role, location or pay.
Why was no ATS detected for a company? The company may use an ATS that is not supported yet (iCIMS, SuccessFactors, Teamtailor, JOIN and others), host jobs on its own site, or load the job widget with JavaScript that hides the board link. If you know the board URL, paste it directly.
Why is a domain guess sometimes rejected? Generic names collide: the Ashby board ramp belongs to ramp.com, not to ramp.network. A guess is only accepted when the board and the domain are clearly linked. Rejected guesses are listed in the row's notes, and you can paste the board URL directly if it is the right one.
Workday. Results are paged 20 at a time until Max jobs per company matching postings are collected (with filters or only-new-jobs mode, up to 5 times that number of postings are scanned, at least 500 and at most 2,000 per company). Departments are not exposed by Workday's public API, so the department filter excludes Workday jobs. Postings with several locations show all of them only when descriptions are on. Without descriptions, postedAt comes from Workday's "Posted N Days Ago" text, and postings older than 30 days have no date.
Salary coverage depends on what the company publishes. Structured fields are used when present. The text parser only accepts ranges with an explicit currency, a pay keyword nearby and plausible values. Single numbers, bonuses and stipends are skipped on purpose, so it misses some ranges rather than invent them.
Speed and politeness. Requests to any one host are limited to about 2 per second. Greenhouse, Lever, Ashby, Workable, Recruitee and Personio boards take one or two requests per company. Workday and SmartRecruiters descriptions take one request per job.
Blocked websites. Some company homepages block automated visits. Detection then relies on the domain guesses, and the row explains what happened. ATS APIs are not affected. A proxy can be set in the input.
Responsible use. The Actor reads public job postings that companies publish through their ATS job-board feeds. It does not log in and does not collect applicant data. Job ads can contain recruiter names or contact emails written by the company. Process them in line with the GDPR and local law, and respect each site's terms when you republish content. Link back to the original jobUrl when you show jobs to others.