{"slug": "scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call", "title": "Scrape any company's job postings — Greenhouse, Lever & Ashby, with one API call", "summary": "A developer built a job postings scraper that normalizes data from six major ATS platforms — Greenhouse, Lever, Ashby, Workable, SmartRecruiters, and Recruitee — into a single API call. The tool auto-detects the ATS from a company slug or URL and returns one normalized row per job, including structured compensation data from Ashby boards. For example, all 727 OpenAI roles carry published pay ranges, and 460 are flagged remote.", "body_md": "Almost every tech company's job board runs on one of a handful of ATS platforms — Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee. And nearly all of them expose a **public, documented JSON API** for their postings.\n\nWhich means \"scrape job postings\" isn't really a scraping problem. It's a *normalization* problem: six different response shapes, board-slug discovery, HTML-encoded descriptions, and compensation data that's structured differently everywhere it exists at all.\n\nHere's the DIY version, the one-call version, and one genuinely underrated thing hiding in this data.\n\nNo key, no auth. These are live right now:\n\n```\n# Greenhouse\ncurl \"https://boards-api.greenhouse.io/v1/boards/stripe/jobs\"\n# Lever\ncurl \"https://api.lever.co/v0/postings/palantir?mode=json\"\n# Ashby\ncurl \"https://api.ashbyhq.com/posting-api/job-board/openai\"\n```\n\nAt the time of writing that's **518 open roles at Stripe, 280 at Palantir, and 727 at OpenAI** — three calls, three completely different JSON shapes.\n\nGreenhouse nests `offices`\n\nand `departments`\n\nas arrays of objects. Lever flattens everything into `categories`\n\n. Ashby puts the city in `location.name`\n\nand hides compensation behind a separate `includeCompensation=true`\n\nflag. Descriptions come back as escaped HTML on some, Markdown-ish on others. Multiply by six platforms and you've got a weekend project plus ongoing maintenance every time one of them changes.\n\n[Job Postings API](https://apify.com/fetchbase/job-postings-scraper) auto-detects which ATS a company uses — from a bare slug or a full careers URL — and returns one normalized row per job. Here's a **real, unedited** record from a live run:\n\n```\ncurl -X POST \"https://api.apify.com/v2/acts/fetchbase~job-postings-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"companies\": [\"stripe\", \"gitlab\", \"https://jobs.ashbyhq.com/openai\"] }'\n{\n  \"company\": \"stripe\",\n  \"ats\": \"greenhouse\",\n  \"id\": \"7954688\",\n  \"title\": \"Account Executive, AI Sales (Grower)\",\n  \"department\": \"1654 Account Executives (AI)\",\n  \"location\": \"San Francisco, CA\",\n  \"remote\": null,\n  \"url\": \"https://stripe.com/jobs/search?gh_jid=7954688\",\n  \"publishedAt\": \"2026-07-21T18:51:19-04:00\",\n  \"salary\": null,\n  \"description\": \"## Who we are\\n\\n### About Stripe\\n\\nStripe is a financial infrastructure...\"\n}\n```\n\nNote `remote`\n\nand `salary`\n\nare `null`\n\nthere — and that's the honest part. **Those fields are only as good as what the ATS publishes.** Greenhouse boards frequently omit both. The actor normalizes the shape; it can't invent data the source doesn't expose.\n\nWhich brings us to the interesting bit.\n\nAshby boards expose structured compensation, and plenty of companies leave it on. Of those **727 OpenAI roles, all 727 carry a published pay range** — things like `$257K – $335K • Offers Equity`\n\n. **460 of them are flagged remote.**\n\nThat is a real, public, structured compensation dataset that most people assume you have to buy from Levels.fyi or scrape out of rendered HTML. It's sitting behind a GET request.\n\nUseful inputs while you're exploring:\n\n| Input | Does |\n|---|---|\n`companies` |\nSlugs or careers URLs — mix ATSes freely in one run |\n`remoteOnly` |\nKeep only roles the board flags remote |\n`titleFilter` |\nSubstring match on title (`\"engineer\"` ) |\n`maxJobsPerCompany` |\nCap big boards (default 1000) |\n`includeDescriptions` |\nSet `false` for a fast, light index |\n\nYou're billed per job returned, so filters cut cost as well as noise.\n\n**A \"who's hiring in AI\" snapshot.** One run across several labs, compare volume and department mix:\n\n**A remote-jobs alert.** `remoteOnly`\n\n+ `titleFilter: \"engineer\"`\n\nacross your target companies, on a schedule, diffed against yesterday's dataset → new postings to Slack:\n\n**Comp research.** Pull a whole Ashby board and you get ranges attached to titles and locations:\n\n[Scrape OpenAI's openings]— 727 live roles, all with pay ranges\n\n**Hiring as a market signal.** Posting counts over time are a leading indicator — teams that are shipping are hiring, and teams in trouble quietly stop. Snapshot weekly and you've built a trends dataset nobody sells you.\n\nThese are *intended-use, documented* endpoints. No bot walls, no proxy budget, no 3am breakage when a careers page gets redesigned. The tedious part — ATS detection, six-way shape merge, HTML→Markdown, comp parsing — is the part worth not rewriting yourself.\n\nPay per job returned, failed runs cost nothing, and Apify's free credits cover plenty of testing. The rest of the utility suite lives at [apify.com/fetchbase](https://apify.com/fetchbase).\n\n*Built this because job data shouldn't require scraping infrastructure. If you want another ATS supported or normalized salary output, say so in the comments or the actor's Issues tab.*", "url": "https://wpnews.pro/news/scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call", "canonical_source": "https://dev.to/quantoracle/scrape-any-companys-job-postings-greenhouse-lever-ashby-with-one-api-call-4db", "published_at": "2026-07-22 02:11:12+00:00", "updated_at": "2026-07-22 02:33:01.655173+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence"], "entities": ["Stripe", "Palantir", "OpenAI", "Greenhouse", "Lever", "Ashby", "Apify", "Levels.fyi"], "alternates": {"html": "https://wpnews.pro/news/scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call", "markdown": "https://wpnews.pro/news/scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call.md", "text": "https://wpnews.pro/news/scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call.txt", "jsonld": "https://wpnews.pro/news/scrape-any-company-s-job-postings-greenhouse-lever-ashby-with-one-api-call.jsonld"}}