Company Career Page Jobs Scraper avatar

Company Career Page Jobs Scraper

Pricing

from $1.50 / 1,000 job listing returneds

Go to Apify Store
Company Career Page Jobs Scraper

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

Juddroid

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

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 (detectionMethod plus 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 → board example is 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

ATSExample inputHow jobs are readNotes
Greenhousevercel.com, boards.greenhouse.io/vercel, job-boards.greenhouse.io/vercelPublic board API, one request per companyDescriptions included; pay ranges when the company publishes them
Leverspotify.com, jobs.lever.co/zoox, jobs.eu.lever.co/xPublic postings API, one requestStructured salaryRange when present; workplace type
Ashbylinear.app, jobs.ashbyhq.com/openaiPublic job-board API with compensationStructured compensation; company website used for verification
Workdayhttps://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite, any *.myworkdayjobs.com or myworkdaysite.com URLPublic CXS JSON API, 20 jobs per pageDescriptions need one request per job (toggle Include job description)
SmartRecruitersjobs.smartrecruiters.com/Ubisoft2Public postings API, 100 jobs per pageDescriptions need one request per job
Workablehuggingface.co, apply.workable.com/huggingfacePublic widget and board APIsDescriptions included
Recruiteechannable.recruitee.com, or a Recruitee careers site on the company's own domain (https://jobs.channable.com)Public offers APIStructured salary when published
Personioottonova.jobs.personio.de, ottonova.dePublic XML job feedGerman-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:

  1. 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.
  2. 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.
  3. domain_slug_guess: the company name is derived from the domain (linear.app → linear, plus a hyphen-free variant and a variant without prefixes like get/try or suffixes like hq/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.
  4. 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").

FieldDescription
typejob or company_status
company, companyDomainCompany name (from the ATS when available) and registrable domain
ats, atsBoardUrlgreenhouse, lever, ashby, workday, smartrecruiters, workable, recruitee or personio, and the board URL
detectionMethoddirect_ats_url, domain_slug_guess, careers_page_scan or homepage_scan
jobIdThe ATS job ID (stable between runs, used for only-new-jobs mode)
title, department, teamAs published on the board
locations[]All locations of the job
isRemote, workplaceTyperemote, hybrid, onsite or null when the ATS doesn't say
employmentTypefull_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, updatedAtISO timestamps (Workday without descriptions: day precision from "Posted 3 Days Ago")
jobUrl, applyUrlJob page and application link
descriptionText, descriptionHtmlPlain-text description (default on); HTML only when Also include description HTML is on
isNewtrue in only-new-jobs mode, null otherwise
input, scrapedAtThe input line this row came from, and the time of the scrape
status, message, notesStatus 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

  1. Paste your companies into Companies, one per line: domains, careers pages or ATS board URLs.
  2. Set Max jobs per company. It caps both the result size and the cost per company.
  3. Optionally add filters: title keywords, excluded title keywords, locations, remote only, departments, posted within N days. Filtered-out jobs are not charged.
  4. Keep Include job description on for full text and salary parsing. Turn it off to make Workday and SmartRecruiters boards much faster.
  5. 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)

  1. Turn on Only new jobs since the last run and pick a Snapshot store name for this watchlist, for example sales-targets-q4.
  2. Run it once. The first run returns every current job: this is your baseline.
  3. Add a Schedule in Apify Console (daily or weekly) with the same input.
  4. 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 text line 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.

RunJobs returnedCost
10 companies × 50 jobs500$0.75
100 companies × 30 jobs3,000$4.50
1,000 companies, 20 jobs each after filters20,000$30.00
Weekly monitoring of 200 companies, about 3 new jobs each600 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=overview for 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 companyDomain from 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.