Google Jobs Scraper - Job Postings API avatar

Google Jobs Scraper - Job Postings API

Pricing

$2.00 / 1,000 jobs

Go to Apify Store
Google Jobs Scraper - Job Postings API

Google Jobs Scraper - Job Postings API

Google Jobs and job postings scraper: get job title, company, location, posted date, salary, full description and every apply link for any search. Deduped with a stable job id. US, UK, Canada, India, Singapore, Brazil, Mexico.

Pricing

$2.00 / 1,000 jobs

Rating

0.0

(0)

Developer

Redomic

Redomic

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 hours ago

Last modified

Security

Limited permissions

Share

Google Jobs Scraper - Job Postings API

For recruiters, job boards and labour-market analysts who need fresh postings as data: enter one job search or up to ten at once, plus a location, and get the matching Google Jobs listings as flat rows (title, company, location, workplace type (Remote/Hybrid/Onsite), posting date, salary as numbers with an ISO currency, job type, full description and the first apply link in its own column, plus every other apply link), with a stable job id for dedupe across runs and across the searches in one run.

Reliability: 0 of 4 runs failed/timed out/aborted in the last 30 days (0.0%). See ./CHANGELOG.md#06.

Why this one

  • Bounded run time: Each run has a time budget (120 seconds by default) and every request has a timeout. When the budget runs out you keep what was found, and a status row says partial.
  • Salary as numbers: salaryMin, salaryMax, an ISO 4217 salaryCurrency (USD, CAD, GBP...) and salaryPeriod. When Google shows no salary chip, a pay range written in the title or description ("Day Rate: £400-£495 per day") is read instead, and salarySource says where it came from.
  • Pay per job, nothing else: You are charged only for job rows delivered. Searches, retries, duplicates and status rows cost nothing. There is no start fee and no per-page fee.
  • No bill shock: maxJobs caps the rows (and the price) of every search, and your run's maximum cost is respected: the run stops cleanly at it.
  • Real apply links: Apply links point at the employer or job board page (Indeed, LinkedIn, Lever, Workday and so on), not at Google redirects, and duplicates are removed.
  • Personal data left out: By default, recruiter and contact person names, personal email addresses, and phone numbers next to them are removed from descriptions. Company names and role mailboxes such as careers@ or hr@ stay.
  • No wasted pages: Extra Google searches only run while they keep finding new jobs (see below).

Countries

United States, United Kingdom, Canada, India, Singapore, Brazil and Mexico, each checked with a real jobs page. Google has turned the jobs view off in the EU and EEA, so EU countries cannot be searched. Australia and Japan are not offered: when checked on 2026-10-30, Google did not serve the jobs view there.

Output

One row per job, then one status row per search. Example values come from Google pages captured on 2026-10-30 (the default input's first page). When queries holds several searches, each job row's query says which search found it, and the status rows at the end say how each search went.

FieldExampleMeaning
jobIdAIPUj2dXDu-T_aYiAAAAAA==Google's job id. The same posting keeps it across runs
fingerprintcc5f99e723c63129Hash of title, company and location, for matching across sources
titleForward Deployed Software Engineer (Recent Graduate) - New YorkJob title
companyCrossCountry ConsultingEmployer
locationNew York, NYThe job's location as Google shows it (Anywhere for remote)
workplaceTypeOnsiteRemote, Hybrid, Onsite, or null (derived from location and title)
viaIndeedSite Google took the listing from
postedText3 days agoPosting age as shown (missing on some listings)
postedAt2026-10-27Posting date worked out from postedText
ageDays3Days since posting
salaryText$110K–$140K a yearSalary as shown by Google, or the range read from the title or description
salaryMin, salaryMax110000, 140000Parsed salary range
salaryCurrency, salaryPeriodUSD, yearISO 4217 currency code (a bare $ follows the country: CAD on Canada, SGD on Singapore) and period (hour, day, week, month, year; null when not stated)
salarySourcechipchip (Google's salary chip), title or description (read from the text); null when no pay is shown
jobTypeFull-timeEmployment type
qualificationNo degree mentionedDegree chip, when shown
benefits["Health insurance"]Benefit chips
descriptionBy joining our team as a Forward Deployed Engineer (FDE), you will serve as...Full job description, line breaks kept
highlights{"qualifications": ["Ability to learn continuously, ..."], "benefits": [...], "responsibilities": [...]}Google's job highlights
applyUrlhttps://www.indeed.com/viewjob?jk=635bc04355b2a209&...The first apply link, flat, for spreadsheets
applySourceIndeedSite of the first apply link
qualificationsText, responsibilitiesText, benefitsTextAbility to learn continuously, ...Google's job highlights as plain text, one item per line
applyLinks[{"source": "Indeed", "url": "https://www.indeed.com/viewjob?jk=635bc04355b2a209&..."}, {"source": "Lever", "url": "https://jobs.lever.co/crosscountry-consulting/..."}]Deduped apply links
sourceSites["Indeed", "Built In NYC", "ZipRecruiter", "Lever", "LinkedIn"]Every site the job is listed on
googleUrlhttps://www.google.com/search?ibp=htl;jobs&q=software+engineer+New+York&htidocid=AIPUj2dXDu-T_aYiAAAAAA%3D%3D&hl=en-USThe job on Google
querysoftware engineerYour query
searchLocationNew YorkYour location input (null when empty)
countryUSYour country preset
searchQuerysoftware engineer New YorkExact text sent to Google for the page the job came from
searchVariantnullRefinement that found the job (since yesterday, full time, senior...); null for the plain search
scrapedAt2026-10-30T10:00:00+00:00When the row was scraped (UTC)
firstSeenAt2026-10-30T10:00:00+00:00Monitor mode only (onlyNewJobs: true): when this job was first seen by this search (UTC, ISO 8601); the same stamp is kept in the monitor history for later runs

The status row has these fields (filter on _status to separate it from the jobs):

FieldExampleMeaning
_statusokok; partial (stopped by the time budget or spend limit, some pages failed, or the page layout looked wrong); empty (Google has no jobs for this search); blocked (Google refused every attempt); error (Google returned a jobs page the parser could not read; the run fails so it gets fixed)
query, searchLocation, countrysoftware engineer, New York, USYour input
rows20Job rows returned
pagesFetched3Google pages requested
pagesFailed0Pages that failed after retries
stopReasonmaxJobsWhy the search stopped: maxJobs (reached your limit), time budget, spend limit, no jobs for this search (page one was empty), first page not full (page one had under 9 jobs), first page failed, low yield (refined searches stopped paying off), no new jobs (4 refined searches in a row found nothing new), blocked (most pages failed), all refinements tried, or parser found no jobs on a jobs page. It starts with degraded parse; when most jobs on a page missed company, location or apply links, and ends with ; last error: ... when pages failed

Input

FieldTypeDefaultMeaning
querystringsoftware engineerThe job search, as you would type it into Google Jobs, for example software engineer. Used when queries is empty
queriesarray of strings[]Up to 10 job searches run in order in one run, for example ["software engineer", "data analyst"]. Leave empty to use query. All searches share location, country and the filters below and one time budget; a job found by an earlier search is not returned again under a later one. maxJobs applies per search, and one status row is written per search
locationstring""City, region or remote, as plain text. Empty searches the whole country (outside the US the country name is added to the search, since Google returns nothing for a bare query there)
countryenumUSGoogle edition: US, GB, CA, IN, SG, BR, MX
datePostedenumanyany, today (since yesterday), 3days, week, month
jobTypeenumanyany, fulltime, parttime, contract, internship
maxJobsinteger50Upper limit on job rows per search, 1 to 200. See below for how many a search can really reach
timeBudgetSecsinteger120Total budget for the whole run (60 or more), shared by every search in queries; stop at this time and keep what was found
includeContactNamesbooleanfalseKeep recruiter and contact names in descriptions
onlyNewJobsbooleanfalseMonitor mode: return (and charge) only jobs that earlier runs of the same search have not delivered; each delivered row carries firstSeenAt, when it was first seen
remoteOnlybooleanfalseReturn only remote jobs (workplaceType is Remote: location "Anywhere" or "Remote" in the title or location)
jobIdsarray of strings[]Detail lookup instead of a search: Google job ids or Google Jobs URLs from an earlier run; returns only those jobs (see below). Leave empty for search mode

Example:

{ "query": "software engineer", "location": "New York", "country": "US", "maxJobs": 20 }

Several titles in one run:

{ "queries": ["software engineer", "data analyst"], "location": "New York", "country": "US", "maxJobs": 20 }

Each search runs in turn, rows are tagged with the search that found them in query, and a posting that matches two searches is returned once, under the first one. You pay only for rows delivered.

How it gets more than 10 jobs

Google shows about 10 jobs per search. To reach maxJobs the Actor runs refined versions of your search, the same ones Google's own filter chips use (posted since yesterday, last 3 days, full time, contract, senior, remote and so on), and keeps only jobs it has not seen yet. Every refinement still matches your query, location and filters. The first search plus its refinements make at most 23 Google searches when datePosted and jobType are both any (4 date windows, 4 job types, 8 seniority/remote words, 6 job type and date pairs), 13 when exactly one of them is set (the refinements of the filter you set are skipped, and so are the pairs), and 9 when both are set (the 8 seniority/remote words only). At about 10 jobs a page that is at most about 230 jobs before overlap; after duplicates are removed a search usually reaches far fewer, and maxJobs stops at 200.

Refinements only narrow your search, so the Actor does not run them when the first page has fewer than 9 jobs, and stops them as soon as a group of refined searches averages fewer than 2 new jobs each, or 4 in a row find nothing new. It also stops at maxJobs, at the time budget and at your spend limit. A narrow search (a rare role in a small town, or datePosted: today) often ends after the first page; the status row then says ok with the number found.

Duplicates are removed by jobId and by fingerprint (same title, company and location), including across the searches in one run. Two separate postings that look identical (same title, company and location under two Google ids, for example the same role advertised twice) come back once.

Job details lookup

For pipelines that already hold Google job ids (saved from an earlier run, or in a CRM): pass them in jobIds and get back only those jobs, with the full description and every apply link, instead of re-running a search. Each entry can be a bare jobId or a full Google Jobs URL (the googleUrl of an earlier row); the id is read from its htidocid parameter. One Google page is fetched per id, in the order given, and capped by maxJobs like a search. query, location, datePosted, jobType and remoteOnly are ignored in this mode; country picks the Google edition. You pay per job row delivered, as usual; an id Google no longer serves gives no row and costs nothing (a run where none of the ids are found ends empty).

Example input:

{ "jobIds": ["AIPUj2dXDu-T_aYiAAAAAA=="], "country": "US" }

Real output for that id, from the page captured on 2026-10-30 (the same row shown in the Output table above):

FieldValue
jobIdAIPUj2dXDu-T_aYiAAAAAA==
titleForward Deployed Software Engineer (Recent Graduate) - New York
companyCrossCountry Consulting
locationNew York, NY
postedText3 days ago
salaryText$110K–$140K a year
description3,671 characters, starting By joining our team as a Forward Deployed Engineer (FDE), you will serve as...
applyLinks8 links, first {"source": "Indeed", "url": "https://www.indeed.com/viewjob?jk=635bc04355b2a209&..."}

The status row ends ok with stopReason: "all job ids tried", rows: 1, pagesFetched: 1 and jobIds: ["AIPUj2dXDu-T_aYiAAAAAA=="].

Pricing

job: $0.002 per job row delivered. No start fee. 1,000 jobs ≈ $2.00; a daily 50-job watch ≈ $3 a month.

Tips

  • Phrase the query like a person would: senior react developer fintech, warehouse jobs no experience.
  • Daily monitoring recipe: save a task with onlyNewJobs: true (and datePosted: "week" to keep each run small), schedule it every morning in Apify Console, and add a "run succeeded" webhook to Slack, Make or n8n, or export the dataset to Google Sheets. Each run returns only jobs you have not received before, each stamped with firstSeenAt, and you pay only for those; the status row says how many were already delivered.
  • Do not use the data to build a competing search engine. Respect the terms of the sites you apply through.

FAQ

  • Why only about 10 jobs on some searches? Google shows about 10 jobs per search; the Actor widens with refinements only while they keep finding new jobs (see above). A narrow search can end after the first page.
  • Is salary always filled? No. Google shows a salary chip on some listings; otherwise the Actor reads a range written in the title or description. When neither has one, the salary fields are null: nothing is estimated.
  • Can I search the EU? No. Google has switched the jobs view off in the EU and EEA.

What this does not do

It does not log in anywhere, open LinkedIn or Indeed pages, or collect applicant data; it reads Google's public jobs view only. It does not search EU/EEA countries, Australia or Japan. It does not estimate missing salaries.

Sibling Actors: Greenhouse Jobs Scraper with Salaries (every open job on a company's Greenhouse careers board, with published pay ranges) and Google Trends.

Other languages

Español

Escribe una búsqueda de empleo y una ubicación y obtén los anuncios de Google Jobs como filas: puesto, empresa, ubicación, fecha de publicación, salario, tipo de empleo, descripción completa y todos los enlaces para postularse, con un id estable para quitar duplicados entre ejecuciones. Para usarlo, indica query (por ejemplo software engineer), location (por ejemplo New York) y country, y pulsa Start. Pagas solo por cada empleo entregado.

Deutsch

Gib eine Jobsuche und einen Ort ein und erhalte die passenden Google-Jobs-Anzeigen als Zeilen: Titel, Firma, Ort, Veröffentlichungsdatum, Gehalt, Anstellungsart, vollständige Beschreibung und alle Bewerbungslinks, mit einer stabilen Job-ID zum Entfernen von Duplikaten über mehrere Läufe. So startest du es: query (zum Beispiel software engineer), location (zum Beispiel New York) und country ausfüllen und auf Start klicken. Du zahlst nur pro gelieferter Stelle.

Français

Saisissez une recherche d'emploi et un lieu et recevez les offres Google Jobs correspondantes sous forme de lignes : intitulé, entreprise, lieu, date de publication, salaire, type de contrat, description complète et tous les liens de candidature, avec un identifiant stable pour dédoublonner d'une exécution à l'autre. Pour le lancer, remplissez query (par exemple software engineer), location (par exemple New York) et country, puis cliquez sur Start. Vous ne payez que pour chaque offre livrée.

Português

Digite uma busca de vaga e um local e receba os anúncios do Google Jobs como linhas: título, empresa, local, data de publicação, salário, tipo de contrato, descrição completa e todos os links de candidatura, com um id estável para remover duplicatas entre execuções. Para rodar, preencha query (por exemplo software engineer), location (por exemplo São Paulo) e country (por exemplo BR) e clique em Start. Você paga apenas por vaga entregue.

Use it from AI agents (MCP) and Python

AI agents. Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client through the Apify MCP server. The agent reads the input schema, so a plain request is enough.

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

Python. pip install apify-client, then:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("redomic/google-jobs").call(run_input={"query": "software engineer", "location": "New York", "country": "US", "maxJobs": 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

More from us