DEV Community

0xGollum
0xGollum

Posted on

Two free, unauthenticated JSON APIs most job-scraping tutorials never mention

If you've ever scraped job postings, you've probably fought Google Jobs search results or LinkedIn's anti-bot wall. Here's a source most tutorials skip entirely: Greenhouse and Lever, the two ATS platforms behind a huge share of tech company career pages, both expose fully public, unauthenticated, versioned JSON APIs. No login, no key, no scraping fragility.

curl https://boards-api.greenhouse.io/v1/boards/stripe/jobs
curl https://api.lever.co/v0/postings/some-company?mode=json

Both return clean structured JSON: title, location, department, posting date, direct URL. I built a small watcher on top of both for a side project. One gotcha worth sharing, because it's the kind of thing that silently degrades data quality without ever throwing an error.

The field that's just... missing, until you ask differently

The Greenhouse jobs endpoint returns a job object with about a dozen fields — title, location, company_name, first_published, absolute_url. No "departments" field at all. Not null, not empty — absent from the payload entirely.

Add ?content=true to the URL (documented as "include full job description HTML") and the same job object now also includes a departments array. The department data was never conditional on anything you'd guess from the parameter's name or docs — it just happens to be bundled with the heavier, content-inclusive response.

curl https://boards-api.greenhouse.io/v1/boards/stripe/jobs?content=true

Nothing failed without it. No error, no warning, just a field that's quietly absent — the kind of gap you only notice if you actually inspect real output field-by-field instead of trusting that "the request succeeded" means "I got everything I expected."

Lever's date format is a landmine for anyone who assumes ISO strings

Lever's postings return createdAt as an epoch timestamp in milliseconds (not seconds — a common source of off-by-1000x bugs when parsing). Greenhouse, meanwhile, gives you first_published as an ISO 8601 string. Building one pipeline that ingests both without normalizing this difference will silently produce garbage dates from whichever source you tested less.

Two free, solid data sources — but "solid" doesn't mean "identical," and the assumption that two similar-looking public APIs share a schema is exactly the kind of thing that only breaks in production, on the source you didn't write your first test against.


Part of a small portfolio of data actors I maintain — signal over data dump, always tested against the real source before shipping. 0xGollum, feeding the data mines.

Top comments (0)