Google Jobs Scraper API avatar

Google Jobs Scraper API

Pricing

from $1.67 / 1,000 jobs

Go to Apify Store
Google Jobs Scraper API

Google Jobs Scraper API

Scrape Google's jobs results into structured postings: title, company, location, posting source, posted date, employment type, full description and every apply link. Priced per job, and never charged for a search that returns nothing.

Pricing

from $1.67 / 1,000 jobs

Rating

0.0

(0)

Developer

Shakamize

Shakamize

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 hours ago

Last modified

Share

Turns a Google jobs search into structured job postings: title, company, location, the board Google indexed it from, when it was posted, employment type, salary and benefits where Google shows them, the full description, and every apply link - typically four to eight per posting, as direct employer and board URLs rather than Google redirects.

Google's jobs results are an aggregator. One search returns postings syndicated from LinkedIn, Indeed, Glassdoor, ZipRecruiter, SimplyHired, company careers sites and niche boards, already merged and de-duplicated by Google. That cross-board feed is the thing worth scraping, and nothing else assembles it.

Priced per job, at $0.002. A search that returns nothing is never charged.

Use it to build or fill a job board, track which roles a company is hiring for, watch a competitor's headcount grow, or collect postings and apply links for a recruiting pipeline. Coverage is Google's aggregation across boards and employer sites rather than one board's full inventory, so what you get follows what Google indexes for your query; for a single board's complete catalogue, scrape that board directly.

How many Google jobs you can actually scrape per search, and why it is 10

Read this before comparing us to anything else on the store.

Google renders exactly 10 jobs per request, and its "load more" control does nothing for a non-browser client. Measured live on 2026-08-29:

What was triedResult
&start=10, &start=20, &start=30a 200KB page with no jobs widget at all
the infinite-scroll cursor on its own async endpointHTTP 200 and an empty control frame
scrolling the page to the cursor in a real browserno request fired; still 10 jobs
&tbs=qdr:dkills the jobs widget entirely

That ten-result ceiling is Google's, and it is why orgupdate, the top-ranked actor in this niche, carries an open issue titled "Only 10 results".

More jobs come from Google's own filter links. Set Max jobs per search above 10 and the actor follows the filter links the page itself offers - remote, full time, part time, contract, internship, posted in the last N days - and removes the jobs that repeat. Measured: 9 requests returned 73 distinct jobs for one search. The filter links are read off the page, so they are always in the market's own language, and only links that narrow your search are followed; Google's "related searches" rewrite it, and are ignored.

Every extra request is logged, and when Google offers fewer filters than the jobs you asked for, the log says so rather than quietly returning less.

Which countries Google serves jobs results in

Page size gives it away before the parse does: a market with the widget returns 850KB to 1,050KB, one without returns 200KB to 400KB. Measured 2026-08-29:

MarketJobs resultsNote
United States, United Kingdom, Canadayes
India, Australiayes
Germanyyesonly when the search is worded a certain way
France, Spain, Italyyesonly when queried in the local language
Netherlands, Ireland, Poland, Swedennonothing in any phrasing tried

Spain and Italy are widely documented as dead markets for Google jobs. They are not. They return nothing to an English query and ten jobs to one in Spanish or Italian. Language, not country, is the trigger. This actor picks the language that works for the market you choose, so you do not have to know that.

For the markets that return nothing, the actor says so in the log and writes an error record naming the market, rather than finishing successfully with an empty dataset that reads like a place with no openings.

The wording of a search decides whether Google answers it

This is the single strangest thing about the surface, and it costs the incumbents whole markets:

software engineer jobs in Berlin -> 0 jobs, 209KB
software engineer jobs berlin -> 10 jobs, 885KB

Same country, same language, same day. So a search here is a ladder: the actor tries one phrasing, and if Google renders no jobs widget it re-words the search and tries again. That second attempt is what makes Germany work at all, and it costs an extra request only when the first phrasing fails.

Location: you get the place you asked for

"Location issue" is the highest-subscribed complaint in this niche, so:

  • A location is required. Google scopes its jobs results to a place, and a bare keyword usually returns nothing. The actor refuses the run and says why, rather than returning arbitrary results.
  • Postings from elsewhere are dropped. Google's own "remote" filter link, on a Chicago search, returns postings in Japan, Dallas and Hartford. Those are not answers to the question you asked, so by default they do not reach your dataset - and the log names every one that was dropped. Set Location match to off to keep them.
  • Verified: nurse jobs in Austin, TX returned 10 of 10 in Austin; Seattle, London, Madrid and Toronto likewise.

What you get back for each job

One record per posting:

FieldWhat it is
jobIdGoogle's own identifier, stable across searches and runs
title, companyName, locationas Google writes them
viathe board or careers site the posting was indexed from
postedAt, postedAtTextan ISO date, plus Google's own wording in the market's language
employmentType, salary, benefitsread from the labels beside the posting
chipsevery label, raw, so nothing is lost to classification
highlightsGoogle's own extraction: qualifications, responsibilities, benefits
descriptionthe full posting text, including what the page hides behind "Show more"
descriptionIsTruncatedtrue when Google served a preview instead of the whole posting
applyLinksevery route, as direct URLs with the board each belongs to
searchQuery, searchKeyword, ...which search found it, including a re-worded one

descriptionIsTruncated is worth knowing about. Google serves two layouts. One carries the whole posting - about 4,500 characters in our measurements - and the other only a short preview of about 400, and which one you get depends on the market. Rather than present a preview as a full description, the actor labels it. Follow an apply link for the rest.

How duplicate job postings are removed

"Duplicates" is the second-loudest complaint in this niche. Every job carries Google's own identifier, and repeats are removed exactly on that id, never by fuzzy matching on title and company. This applies within a run automatically, across every filter the fan-out follows. Turn on Only jobs not seen before to also skip jobs stored by previous runs, remembered in a named key-value store so separate saved searches keep separate memories.

How to filter Google Jobs by company, employment type, date and remote

Every filter runs over what was parsed, never over the query sent to Google. Google's filters are localised free text with no stable identifier, so asking Google to filter would mean guessing a phrase and silently returning the wrong jobs when the guess is wrong.

  • Employment type - full-time, part-time, contractor, internship and so on
  • Remote only
  • Posted within N days - jobs Google gives no age for are dropped, never assumed recent
  • Only these companies / Exclude companies - useful against staffing agencies
  • Only these sources - for example only LinkedIn, or only employer sites

Setting any filter makes the actor spend extra requests, so the filters have material to work on.

One event, one job. A run costs jobs x $0.002, which is arithmetic you can do before you start it.

"Charged $1.21 but returned zero results" is on the usage leader's issue tracker. Here, a job is charged after its record is stored, so a search that returns nothing costs nothing, and the dataset says so:

{
"error": "no_jobs_found",
"errorDescription": "Google rendered no jobs for \"welder jobs in Nuuk\" or \"welder jobs Nuuk\" in US. Nothing was charged.",
"input": "welder / Nuuk"
}

Every search leaves a record - a job or an explanation - so a partial run can always be reconciled against what you asked for, and an empty market is never confused with a page that could not be read.

Proxies for scraping Google Jobs without getting blocked

Google's jobs results are fetched through Apify's unblocking service, which is configured by default and needs nothing from you. A plain datacenter or residential address is redirected away from the jobs results, so changing this is rarely useful.

Errors: what happens when a Google Jobs search cannot be scraped

CodeMeaning
no_jobs_foundGoogle rendered no jobs for either phrasing of this search. Not charged.
request_failedThe page could not be read after retries. Not charged.

FAQ

Google's jobs vertical serves ten results per request and publishes no working cursor for a non-browser client. &start= offsets do nothing, the load-more token does nothing for a non-browser client, and scrolling a real browser to the load-more sentinel fires no network request at all.

More jobs come from Google's own filter links, which this actor follows. It also states the true ceiling up front rather than letting you wonder:

WARN 40 more job(s) were asked for, and Google offers only 2 filter(s) on this
search, so it can return at most 30. This is Google's ceiling, not a cap
applied here.

Will I be charged if the search returns nothing?

No. Charging is per job posting stored, at $0.002 each. On a billed run with two searches on 2026-09-01, one returning ten jobs and one returning none, the charge was exactly {"job":10}. The empty search consumed requests on our side and nothing on yours.

Jobs dropped by your location or company filters are not charged either. If it is not in your dataset, it is not on your bill.

How do I cap what a run can cost?

maxJobsPerQuery caps each search, maxJobs caps the whole run. Because the billed unit is a stored job, those two bound the bill absolutely. Ten jobs is $0.02; a 19-job run measured on 2026-09-01 cost $0.038.

Why does my search return nothing when the same search works in my browser?

Whether Google renders the jobs widget depends on the wording and language of the query, not the country. ... jobs in Berlin returns nothing where

... jobs Berlin
returns ten, and Spain and Italy return full results in Spanish and Italian but nothing in English.

This actor retries an alternate phrasing automatically and logs it. If you are judging whether a market has data at all, test more than one phrasing and the local language first.

Why are some jobs missing a salary?

Google publishes pay on roughly 1 to 3 job cards in 10. Across a 19-job run on 2026-09-01, salary was present on 8 of 19, employment type on 18, posted date on 14, and source and benefits on all 19.

That is normal rather than a collapse, and our own coverage monitoring treats it that way. A tool that reports a salary on every posting is inferring it.

Why did jobs get dropped for location?

Google returns postings from elsewhere under its own filters. On an Austin search, the "remote" filter returned postings in Georgia, Kentucky and Colorado. Those are dropped, the drop is reported with the places it dropped, and locationMatch: "off" keeps them if you want them.

Telemetry

The actor reports run health to its maintainer: error codes, the build number, and per-field counts of how often a value was found.

When requests fail, it also sends a small, capped sample of the failures themselves, so that a broken run can be diagnosed and fixed: the Google search URL that was requested, the HTTP status code that came back, and the error with its stack trace. That URL contains the search you asked for - the keyword and the location are part of it. It carries no personal data, but it is your input, and this section says so rather than leave you to find out.

Your proxy configuration and the scraped job listings themselves are never sent. A run that succeeds sends the same summary without the failure sample: how many results it stored, the run and build it came from, and the per-field counts. Nothing about a healthy run is worth hiding, and a run nobody hears about cannot be improved.

Job postings are company data, and that is all this actor returns. It collects no personal data: no recruiter names, no employer contact emails, no applicant information. That is a deliberate limit rather than a missing feature - enrichment of that kind is personal data of EU residents and carries GDPR exposure regardless of whether anyone is signed in.

Only publicly visible search results are read, and nothing is signed into.