All platforms

Google Jobs API

Query Google's postings through one API with ?source=google — plus why the board hides in an AF_initDataCallback blob and every field is addressed by number.

?source=googlesource reference

Google is not a platform. Every multi-tenant source here is software that hosts many employers' boards — one Greenhouse adapter reaches every company on Greenhouse. This one reaches Google, and only Google. company is ignored, because there is exactly one.

It's here because Google is large enough for its jobs to matter on their own, and because it runs a bespoke careers site rather than buying an ATS — so no platform adapter will ever discover it. If you want Google's postings, you write an adapter for Google and you own it forever.

We wrote it: query it with ?source=google. /v1/meta is the authoritative live vocabulary, with the current count per source.

How Google Careers actually works#

No browser, no auth, and — pleasantly — no per-job N+1. The results page server-renders each page of jobs into the HTML as a JavaScript callback, and ?page=N walks it twenty jobs at a time:

BASH
curl "https://www.google.com/about/careers/applications/jobs/results/?page=1"

Buried in that HTML is a blob:

JS
AF_initDataCallback({ key: 'ds:1', data: [[…jobs…], …, 3202], sideChannel: {} });

data[0] is the page of jobs, data[2] is the whole-board total. Page 1 carries the total and the rest of the pages fan out in parallel. Each record already holds the full description — overview, responsibilities and qualifications inline — so there is nothing to fetch twice.

The old search API is gone

Google's /api/v3/search — the clean JSON endpoint most write-ups still point at — is dead (404). And it wouldn't help if it weren't: that per-keyword search capped out around 2,000 results. The no-query listing paginates the entire board with no such cutoff (measured: ~3,200 unique jobs to page 166).

Every field is addressed by number#

The ds:1 record is a positional array, not an object. There are no keys — you read a job by index, and the indices are Google's, not yours:

[0] id   [1] title   [3] responsibilities   [4] qualifications
[9] locations   [10] overview   [14] published (unix seconds)   [20] level

Slot [20] is Google's target_level, decoded against the site's own ?target_level= facet: 1 early, 2 mid, 3 advanced, 5 intern. It's the one field that gives you seniority, and a few short records don't carry it at all.

What bites you#

A shifted index mismaps silently, and nothing throws

Because the record is positional, there is no field name to disagree with. The day Google inserts one element and the description slides from slot [10] to [11], your titles are fine, your ids are fine, and every body is quietly wrong. A named JSON field that vanishes reads null or throws; a reshuffled array keeps returning strings — just the wrong ones.

A throttled page looks like a shrunken board

Google is a complete-return source: the live set — and therefore what expires — is derived from what the scrape returns. So a run that loses pages to throttling looks exactly like a board that shrank, and would expire every job it failed to fetch. The guard is to throw (and retry) when the run comes back with less than 70% of Google's own reported total, rather than bank a decimated board. Fetch the whole thing or fetch none of it.

The data lives in page markup, not an API. It's extracted with a regex over the AF_initDataCallback(...) blob. That's robust enough today and brittle by nature: markup is not a contract.

No structured salary. Nothing in ds:1 carries comp; whatever pay exists is prose inside the qualifications HTML.

Or use ours#

Pagination off a total buried in a JS callback, a positional array read by index, seniority decoded from a facet, and a completeness guard that refuses to expire a throttled board — with Google's rows in the same Job shape as every other source, dedup against the same role on LinkedIn, and the adapter's upkeep being ours instead of yours. Same deal as Amazon, Apple, Uber, TikTok, Microsoft and IBM.

Sources · Quickstart

Every source above normalises onto the same schema, with the hiring company already joined onto each posting.

Get an API key