Google Jobs Scraper — Full Panel, Salary, Apply Links avatar

Google Jobs Scraper — Full Panel, Salary, Apply Links

Pricing

from $1.00 / 1,000 job listings

Go to Apify Store
Google Jobs Scraper — Full Panel, Salary, Apply Links

Google Jobs Scraper — Full Panel, Salary, Apply Links

The full Google Jobs panel for any search — about 90–130 job cards where Google has that many, not the first ten. Title, company, location, source board, posted age, salary when shown, direct apply links and the full description on every row. You are never charged for a job that was not delivered.

Pricing

from $1.00 / 1,000 job listings

Rating

0.0

(0)

Developer

Steadyfetch Team

Steadyfetch Team

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

23 minutes ago

Last modified

Share

Google Jobs Scraper

The full Google Jobs panel, not the first ten results. One search returns about 90–130 job cards where Google has that many — niche searches return every card Google has. Set a row cap and a deadline and the run stops exactly there — no runaway bills.

From $1.00 per 1,000 job listings — all-inclusive pay per event, no start fee, charged only on delivery. Never pay for a job we didn't deliver.

Unofficial. This actor is not affiliated with, endorsed by, or sponsored by Google. "Google" and all related marks are trademarks of Google LLC. It reads only the public jobs panel an ordinary browser sees.

Every row carries charged and missReason, so you can reconcile the invoice from the dataset itself without opening the console. Only rows with charged: true were billed.


Output — a real row

{
"source": "google-jobs",
"sourceJobId": "Ati0AB1gZvCYY_O-AAAAAA==",
"title": "Part-Time Barista/Counter Person 20+ hours",
"company": "Madison Kitchen",
"location": { "raw": "Seattle, WA", "city": "Seattle", "region": "WA", "postcode": null, "country": "US" },
"via": "Poached Jobs",
"postedRelative": "6 days ago",
"salaryText": "$21.30 an hour",
"salary": { "min": 21.3, "max": null, "currency": "USD", "period": "hour" },
"employmentType": "Part-time",
"qualification": "No degree mentioned",
"applyUrl": "https://poachedjobs.com/jobs/seattle-wa-barista-jobs-madison-kitchen-part-time-baristacounter-person-20-hours",
"applyOptions": [
{ "board": "Poached Jobs", "url": "https://poachedjobs.com/jobs/seattle-wa-barista-jobs-madison-kitchen-part-time-baristacounter-person-20-hours" }
],
"descriptionText": "We're busy and we're hiring! …the job's complete description text…",
"jobUrl": "https://www.google.com/search?ibp=htl;jobs&q=part+time+barista+jobs+near+seattle&htidocid=Ati0AB1gZvCYY_O-AAAAAA%3D%3D",
"query": "part time barista jobs near seattle",
"country": "US",
"dedupeKey": "gjobs:Ati0AB1gZvCYY_O-AAAAAA==",
"charged": true,
"missReason": null
}

Plus one search row per searchquery, country, delivered, outcome — and one summary row with delivered, stoppedBy, resumeCursor, datasetId (paste it into resumeFromDatasetId to continue this run later), carriedOver and chargedEvents.

Browse the full live example dataset → — one real run, unedited: five delivered US listings capped at maxItems: 5, the search row that reconciles them, and the run's own summary row last. Five listings delivered, five charged.

Every row ships the real apply links — the direct URLs on the job boards themselves (LinkedIn, Indeed, ZipRecruiter, the employer's own site…), in the same order Google's "Apply" buttons show them — plus the job's full description text and the via source board. jobUrl opens the exact card on Google Jobs.

Agent / API paste-block

Actor: steadyfetch/google-jobs-scraper
Required: queries (array of job searches, e.g. "software engineer jobs in austin")
Optional: location (string — added to searches that don't already name one)
country (ISO-2, default "US" — which country's Google to ask)
maxItems (integer, default 300 — hard cap for the whole run)
maxRunSeconds (integer, default 900 — clean stop, never a timeout kill)
resumeFromDatasetId (string — an earlier run's dataset ID; every listing already
in it is skipped and never charged again)
Charges: job-listing once per delivered job listing
Note: omit a field — or send it as null — to use its default.
Build spec: https://apify.com/steadyfetch/google-jobs-scraper/api
Token: https://console.apify.com/settings/integrations
curl -X POST "https://api.apify.com/v2/acts/steadyfetch~google-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"queries":["software engineer jobs in austin"],"maxItems":50}'

How many jobs one search returns

About 90–130 in covered regions, measured across US and UK searches. A niche search returns fewer because Google has fewer — that is the supply, not a cap. The same job reached by two of your searches is delivered and charged once (Google repeats jobs across related searches; we de-duplicate on Google's own job id). More rows come from more searches: vary the phrasing, the location or the country.

Countries

country picks which country's Google results to ask for. US and GB are verified end to end; other codes are passed to Google as-is and the jobs panel works the same way. The rows come back in English (hl=en).

What you are never charged for

situationmissReasonrun status
Google answered with an access checkCHALLENGEDSUCCEEDED — re-runnable, and the row says so
Google rate-limited the requestTHROTTLEDSUCCEEDED — re-runnable
Google returned a page we could not readSOURCE_UNAVAILABLESUCCEEDED — re-runnable
The search ran and its jobs panel was emptyCLEAN_EMPTYSUCCEEDED — a real answer
A search we could not readUSER_INPUTSUCCEEDED — the row names the fix
Your own maxItems / maxRunSeconds / cost capSTOPPED_AT_LIMITSUCCEEDED — summary row with resumeCursor and the datasetId to continue from

We never guess. An access check is reported as an access check, not as "no jobs found" — a temporary problem is never dressed up as a permanent verdict, and it is never charged.

A search that comes back blocked, rate-limited or unreadable is fetched again before any of those rows ships. That second attempt is on us: a search only reports a miss when the retry came up short too, and either way there is no result fee.

This actor may fail when Google changes things. Failed searches ship as rows with charged: false, the run still SUCCEEDS, and the row says whether re-running can help.

Limits are hard limits

maxItems and maxRunSeconds stop the run exactly where you set them. The run still finishes successfully, the summary row names which limit bound, and resumeCursor lists the searches that were not reached. To collect the rest without paying again for what you already have, re-run the same input with a higher cap and resumeFromDatasetId set to that run's dataset ID (it is on the summary row as datasetId): every listing already in that dataset is skipped — never fetched, never charged — and the new summary's carriedOver says how many. A dataset ID that cannot be read stops the run before it fetches anything, uncharged.

They are limits on the run, not on a container. If Apify moves your run to another server part-way through, or you resurrect a finished run, it picks up from what is already in your dataset: the same job is never delivered twice and never charged twice, and maxItems still means what you typed.

FAQ

Where do the apply links point? At the job boards themselves — the same destinations as Google's own "Apply on …" buttons, with every option listed in applyOptions and the first one in applyUrl.

Why is salary empty on some rows? Because Google did not show one. salaryText is the exact string Google printed and salary is our parse of it; when the card carries no salary both stay null rather than being estimated.

Is the posted date exact? Google publishes a relative age ("6 days ago"), and that is what postedRelative carries. We do not fabricate a timestamp from it.

Does {} charge anything? No job listings are charged. With no searches the run returns uncharged sample rows that show the exact output shape, and it contacts nothing.


Run it from an AI agent (MCP)

Works out of the box from any MCP client (Claude, Cursor, …) via Apify's MCP server — ask for "nurse jobs Google lists in Texas this week" and point it at this actor.

Pin this actor in one click — add this server to your MCP config:

{
"mcpServers": {
"google-jobs": {
"url": "https://mcp.apify.com?tools=steadyfetch/google-jobs-scraper",
"headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
}
}
}

Steadyfetch jobs suite

One actor per source, one job each, the same row shape — so a pipeline built on one source takes the next without a rewrite. All-inclusive pay per event, no start fee, charged only on delivery.

SourceActor
IndeedIndeed Jobs Scraper — Salary, Apply Links, Exact Country
A company's own career site (paste a domain)Company Jobs Scraper — Career Pages by Domain, 9 ATS Boards
Glassdoor, with the employer ratingGlassdoor Jobs Scraper — Employer Star Rating on Every Row
Several boards at once, de-duplicatedJob Board Scraper — Indeed + Career Sites, One Deduped Feed
Google Jobs, with the full panel and apply linksthis actor

The rest of the steadyfetch shelf — same contract everywhere: all-inclusive pay per event, no start fee, charged only on delivery.

FamilyActors
Ad creative intelligenceFacebook · Google Ads video · TikTok · LinkedIn · Google Ads text & OCR
Trends & keywordsGoogle Trends · Trends Now · Breakout keywords · Autocomplete keywords · Keyword volume & CPC · Social trends
YouTube transcriptsYouTube videos · YouTube channels
InstagramReel transcripts · Profile posts
JobsIndeed · Career sites by domain · Glassdoor · Multi-board · Google Jobs
AmazonProducts · Search · Bestsellers · Sellers
Any media fileSpeech to Text · any link or file

Feedback & support

Found an issue? Open it on the Issues tab — we respond within one business day. Feature requests welcome. If this actor earned its keep, a rating helps other buyers find it, and saving it keeps it one click away in your console.