All scrapers

Jobs & careers

Company Career Sites Scraper

greenhouse.io, lever.co, ashbyhq.com, myworkdayjobs.com, smartrecruiters.com, workable.com, recruitee.com

100% Success rate
1.6s Avg response
Bot detection + rate limiting Protection
1,101 calls Measured over

Most companies publish their open jobs through a hosted applicant tracking system (ATS), and every ATS shapes its job data differently. A dedicated plugin endpoint takes the company's career page URL on Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable or Recruitee, or the ATS and the company's board name, detects the ATS and returns every open job in one normalized shape: id, title, the link to the posting and to the application, the main location and every location, country, the remote flag and workplace type (remote, hybrid or onsite), department and team, employment type, posting and update dates, requisition id, salary ranges with currency and interval where the ATS publishes pay, the ATS's own extra fields and, with include_description=true, the full description as text and HTML. Filter by words in the title, location, department or remote only, and cap the count with limit, up to 2,000 jobs per call. A link to one posting returns just that posting with its description. The answer also carries the detected ATS, the company, the board URL, the number of jobs on the board and how many matched. Everything is read from the public job data the ATS serves to its own career pages: no browser, no login and no ATS account.

What you can extract

  • Job id, title and links to the posting and to the application form
  • Main location and every location of the job, country, remote flag and workplace type (remote, hybrid or onsite)
  • Department, team, employment type and requisition id
  • Posting and update dates
  • Salary ranges with minimum, maximum, currency and interval, where the ATS publishes pay
  • Full job description as text and HTML (include_description=true)
  • The ATS's own extra fields, plus the detected ATS, company, board URL, jobs on the board and jobs matched
  • Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable and Recruitee, from a career page URL or the ATS and board name
  • Filters by title words, location, department and remote; up to 2,000 jobs per call

Dedicated endpoints

/jobs/career-site

Jobs from a company career site

Every open job on a career site hosted on Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable or Recruitee, from its career page url, or from provider and company (the board name as in the career URL, such as stripe on Greenhouse or nvidia.wd5/NVIDIAExternalCareerSite on Workday). Each job has id, title, company, provider, url, applyUrl, location, locations, country, remote, workplaceType, department, team, employmentType, postedAt, updatedAt, requisitionId, salary and salaryRanges (min, max, currency, interval), customFields and, with include_description=true, descriptionText and descriptionHtml; a field the ATS does not expose is null. keyword (title words), location, department and remote filter the jobs, limit (1-2,000, default 100) caps them, and proxy_country is optional. The answer adds provider, company, companyName, boardUrl, totalJobs, matchedJobs, resultsCollected, pagesFetched and warnings. A link to one posting returns that posting with its description.

How to scrape it

curl -X POST \
  -H "X-ScrapeUnblocker-Key: $SU_API_KEY" \
  "https://api.scrapeunblocker.com/jobs/career-site?url=https%3A%2F%2Fjobs.ashbyhq.com%2Framp&keyword=engineer"
import requests

resp = requests.post(
    "https://api.scrapeunblocker.com/jobs/career-site",
    headers={"X-ScrapeUnblocker-Key": SU_API_KEY},
    params={"url": "https://jobs.ashbyhq.com/ramp", "keyword": "engineer"},
)
print(resp.text)
import { ScrapeUnblockerClient } from 'scrapeunblocker';

const su = new ScrapeUnblockerClient({ apiKey: process.env.SU_API_KEY });

const board = await su.careerSiteJobs('https://jobs.ashbyhq.com/ramp', {
  keyword: 'engineer',
  includeDescription: true,
});
console.log(board);

Requests are POST and take their parameters in the query string. Browser rendering always happens - there is no flag to enable.

Example response

{
  "provider": "ashby",
  "company": "ramp",
  "companyName": null,
  "boardUrl": "https://jobs.ashbyhq.com/ramp",
  "totalJobs": 165,
  "matchedJobs": 39,
  "resultsCollected": 39,
  "jobs": [
    {
      "id": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
      "title": "Security Engineer, Cloud",
      "company": "ramp",
      "provider": "ashby",
      "url": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
      "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
      "location": "New York, NY (HQ)",
      "locations": [ "New York, NY (HQ)", "Remote (Canada)", "Remote (US)" ],
      "country": null,
      "remote": true,
      "workplaceType": "hybrid",
      "department": "Engineering",
      "team": "Backend",
      "employmentType": "Full-time",
      "postedAt": "2026-04-07T17:12:35.753+00:00",
      "updatedAt": null,
      "requisitionId": null,
      "salary": {
        "min": 211400.0,
        "max": 290600.0,
        "currency": "USD",
        "interval": "year",
        "text": "$211.4K - $290.6K"
      },
      "salaryRanges": [
        {
          "min": 211400.0,
          "max": 290600.0,
          "currency": "USD",
          "interval": "year",
          "text": "$211.4K - $290.6K"
        }
      ],
      "customFields": null,
      "descriptionText": null,
      "descriptionHtml": null
    },
    {
      "id": "f564dcf9-9390-4a3f-896f-8047a5086040",
      "title": "Mobile Engineer, Android",
      "company": "ramp",
      "provider": "ashby",
      "url": "https://jobs.ashbyhq.com/ramp/f564dcf9-9390-4a3f-896f-8047a5086040",
      "applyUrl": "https://jobs.ashbyhq.com/ramp/f564dcf9-9390-4a3f-896f-8047a5086040/application",
      "location": "New York, NY (HQ)",
      "locations": [ "New York, NY (HQ)", "Remote (Canada)", "San Francisco, CA" ],
      "country": null,
      "remote": true,
      "workplaceType": "hybrid",
      "department": "Engineering",
      "team": "Mobile",
      "employmentType": "Full-time",
      "postedAt": "2025-07-31T21:58:34.674+00:00",
      "updatedAt": null,
      "requisitionId": null,
      "salary": { "min": 189000.0, "max": 330000.0, "currency": "USD", "interval": "year", "text": "$189K - $330K" },
      "salaryRanges": [
        { "min": 189000.0, "max": 330000.0, "currency": "USD", "interval": "year", "text": "$189K - $330K" }
      ],
      "customFields": null,
      "descriptionText": null,
      "descriptionHtml": null
    }
  ],
  "query": {
    "keyword": "engineer",
    "location": null,
    "department": null,
    "remote": false,
    "limit": 100,
    "includeDescription": false,
    "job": null
  },
  "pagesFetched": 1,
  "warnings": []
}

Read the API docs

Frequently asked questions

Is it legal to scrape company career sites?

Collecting publicly posted job listings from company career sites is lawful in many jurisdictions, but the rules depend on your country, the data you collect and how you use it. A job description sometimes names a recruiter or hiring manager, which can be personal data, so follow the privacy rules that apply to you. ScrapeUnblocker returns the public listings; what you collect and how you use it is your responsibility.

How do I scrape Greenhouse, Lever or Workday jobs without getting blocked?

The /jobs/career-site plugin reads each ATS's public job data, the same JSON its career pages load, with an HTTP client from ISP exits, so no browser and no page rendering is involved. Each worker in a call keeps one connection on one exit while the ATS answers, which matters on Workday, where a large board takes dozens of listing pages, and an exit the ATS refuses (a 403, a 429 or an answer that is not its job data) is rested for that ATS and swapped for a fresh one. In ScrapeUnblocker's benchmark it returned data on 100% of 1,101 calls, each on a different company's job board, about 1.6s per call.

Which ATS platforms are supported, and how do I point at a board?

Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable and Recruitee. Pass the company's career page on the ATS as url, such as https://job-boards.greenhouse.io/stripe, https://jobs.lever.co/palantir, https://jobs.ashbyhq.com/ramp, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite, https://jobs.smartrecruiters.com/Ubisoft2, https://apply.workable.com/huggingface or https://bunq.recruitee.com, and the ATS and board are read from it. Or pass provider and company: the Greenhouse board token, the Lever, Ashby, Workable or Recruitee slug, the SmartRecruiters company id, or tenant.wdN/site for Workday. A careers page on the company's own domain is not read directly; use the ATS link its job buttons point to.

How many jobs can I get per call?

limit caps the jobs returned: 100 by default, up to 2,000. Greenhouse, Ashby, Workable and Recruitee hand over the whole board in one answer, so the filters run on ScrapeUnblocker's side and every matching job comes back. Lever and SmartRecruiters are read 100 jobs per page and Workday 20 per page, and only the pages limit needs are read; the keyword also goes to Workday's and SmartRecruiters' own search, and Workday's location, department and remote filters are used when the board has a matching one. Workday answers at most 2,000 jobs deep into one search, so narrow a bigger Workday board with keyword or location. totalJobs and matchedJobs give the size of the board and of the match, and warnings says when an ATS stopped answering partway.

Do I get salaries and full job descriptions?

Salary comes back where the ATS publishes pay, such as Greenhouse pay ranges, Lever salary ranges or Ashby compensation, when the company fills them in: salary is the main range and salaryRanges every range, each with min, max, currency and interval; otherwise salary is null and salaryRanges empty. The full description comes with include_description=true, as text and as HTML. Greenhouse, Lever, Ashby, Workable and Recruitee include it in the board data; on Workday and SmartRecruiters each description is a separate request, read for at most 300 jobs per call.

How much does it cost to scrape career sites?

Each ATS request that returns data is billed as one request, and pagesFetched shows the exact number: a whole Greenhouse, Ashby, Workable or Recruitee board is 1 request however many jobs it has, Lever and SmartRecruiters are 1 per 100 jobs read and Workday 1 per 20, and on Workday and SmartRecruiters each description read with include_description=true is one more. 1 request = 1 credit, EUR 1.00 per 1,000 on pay as you go, down to about EUR 0.55 per 1,000 on the Ultimate plan. Blocks and timeouts are not billed, and the free trial includes 500 requests with no card.

Related scrapers

Company Career Sites and other names and marks of greenhouse.io, lever.co, ashbyhq.com, myworkdayjobs.com, smartrecruiters.com, workable.com, recruitee.com belong to their owner and are used here only to identify the website this API works with. ScrapeUnblocker is an independent service, not affiliated with, endorsed by or sponsored by the owner of greenhouse.io, lever.co, ashbyhq.com, myworkdayjobs.com, smartrecruiters.com, workable.com, recruitee.com.

Start scraping this site today

Free tier included. No credit card required to test it.