Google Jobs Scraper: Salaries, Apply Links & Full Descriptions
Pricing
from $3.00 / 1,000 jobs
Google Jobs Scraper: Salaries, Apply Links & Full Descriptions
Scrape Google Jobs in 30 countries: title, company, salary (also read from the job text), date, job type, full description and direct apply links. Up to ~90 jobs per search, filters, multiple locations and an only-new-jobs mode for schedules.
Pricing
from $3.00 / 1,000 jobs
Rating
0.0
(0)
Developer
roomy_tweet
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 hours ago
Last modified
Categories
Share
Scrape Google Jobs (Google for Jobs, the jobs panel of Google Search) and get structured job postings for any search in 30 countries: title, company, location, posting date, job type, the full job description, the direct apply links (LinkedIn, Indeed, Glassdoor, the company's own careers page) and the salary as numbers. It works like a Google Jobs API: no login and no proxies to set up, results in JSON, CSV or Excel.
Google Jobs collects listings from thousands of job boards and career sites, so one search here covers what would otherwise take a dozen scrapers.
Why this Google Jobs scraper
- Up to ~90 jobs per search, not just the first 10. A real browser scrolls Google's list the way a person does, until it has what you asked for or Google stops adding jobs.
- Salary on more jobs. When Google shows no salary, the pay stated in the posting is read from its text. On US test searches that raised salary coverage from 40% to 63% of jobs.
- Direct apply links to every site Google lists for the job, with Google's tracking removed. No Google redirects.
- Full description and highlights: qualifications, benefits and responsibilities as lists.
- Google's own filters (date posted, job type, remote) plus filters Google doesn't have: only or exclude companies, and only or exclude source sites. Jobs your filters remove are not charged.
- Only new jobs for daily or hourly schedules: you receive and pay for each job once.
- Many locations at once, Google Jobs URLs pasted from your browser, 30 countries, and labels read in English, Portuguese and Spanish.
- Run report and daily quality check, so a change on Google's side shows up as a warning, not as silently empty results.
What you can use it for
- Recruiting and sourcing: follow new openings for a role, a city or your competitors' companies.
- Job boards and aggregators: fill a niche board with fresh postings and their original apply links.
- Salary benchmarking: compare pay ranges by role, city and job type with numeric
salaryMin/salaryMax. - Labor-market research: demand for skills, remote share, which companies are hiring where.
- Lead generation: companies that are hiring are companies that are growing; filter by company or job type.
- Job alerts: a scheduled run with Only new jobs sends you just what appeared since last time.
- AI agents and RAG: the compact output keeps rows small enough for an LLM.
Quick start
- Type your searches in Search queries, one per line, the way you would type them into Google:
registered nurse,python developer,warehouse associate. - Optionally add Locations (every query runs in every location) and pick the Country.
- Set Maximum jobs per query: 10 is fastest; more is loaded by scrolling, up to ~90.
- Run it, then export the dataset as JSON, CSV or Excel, or read it through the API.
{"queries": ["registered nurse", "software engineer"],"locations": ["Chicago, IL", "Houston, TX"],"country": "us","maxJobsPerQuery": 50}
What you get
| Field | Example |
|---|---|
title, companyName, location | Registered Nurse – ICU · Northwestern Medicine · Chicago, IL |
via | Where Google found it: LinkedIn, Indeed, the employer's careers page… |
postedText, postedDaysAgo, postedAtApprox | "2 days ago", 2, 2026-10-21 |
salaryText, salaryMin, salaryMax, salaryCurrency, salaryPeriod | "$38.20–$57.30 an hour", 38.2, 57.3, USD, HOUR |
salarySource | google (Google's salary label) or description (read from the posting text) |
employmentType, employmentTypes | "Full-time and Part-time", [FULL_TIME, PART_TIME] |
workFromHome, tags | true · Health insurance, Dental insurance, No degree mentioned |
qualifications, benefits, responsibilities, highlights | Bullet lists as Google shows them |
description | The whole posting, line breaks kept |
applyLinks | [{ "title": "Apply on LinkedIn", "url": "https://www.linkedin.com/jobs/view/…", "domain": "linkedin.com" }, …] |
companyLogoUrl, googleJobsUrl, jobId | Google's posting ID, used to skip duplicates |
query, searchLocation, country, position, source, scrapedAt | Search context and rank in Google's list |
Measured on test runs (October 2026, Google US, UK and Brazil): title, company, location, source, full description and apply links on 100% of jobs, and every apply link with its direct URL (2,313 of 2,313). Employment type on about 95% and posting date on 59–74%. Highlights on 94% of US jobs; Google did not show them for the UK and Brazilian searches tested. Salary: see Salary.
Pricing
$3.00 per 1,000 jobs ($0.003 per job saved to the dataset), plus $0.00005 per GB of memory when a run starts ($0.0002 at the default 4 GB). Proxies and compute are included: you pay nothing else.
| You get | You pay |
|---|---|
| 100 jobs | $0.30 |
| 1,000 jobs | $3.00 |
| 200 new jobs every day for a month (Only new jobs) | about $18 |
You are not charged for:
- a job that two of your queries both find (it is saved once);
- jobs your filters remove (company, source, job type, date, remote);
- with Only new jobs, jobs that earlier runs already delivered.
Apify's free plan includes $5 of monthly credit, enough for about 1,600 jobs. Set a maximum cost per run and the run stops by itself when it gets there.
Search options and filters
{"queries": ["registered nurse", "warehouse"],"locations": ["Houston"],"datePosted": "week","employmentType": "PART_TIME","excludeCompanies": ["Example Staffing"],"sources": ["LinkedIn", "Indeed"],"maxJobsPerQuery": 30}
- Locations: every query is searched in every location (2 queries × 3 cities = 6 searches). A job found in two of them is saved once;
searchLocationsays where it was found. - Google Jobs URLs: paste searches straight from your browser (
google.com/search?q=…&udm=8, or a shared job link). Each keeps its own search text, Google domain and language, including filters you picked on Google. They can be mixed with queries; locations are not added to them. - Country picks the Google domain (google.com, google.co.uk, google.com.br, google.de…), so jobs are local to that country. Interface language only changes Google's labels ("2 days ago" / "há 2 dias"); job texts stay as the employer wrote them.
- Date posted, job type and remote are Google's own filters. Google applies them by adding words to the search (
… part time in the last week), in the right language for the country, and the run report shows the exact text used. Google's filters are loose (its "contract" filter also returned full-time jobs in our tests), so jobs whose labels contradict your filter are dropped. Jobs without a label are kept. - Only these companies / Exclude companies match the company name as whole words, ignoring case and accents. "Amazon" matches "Amazon.com Services LLC" but not "Amazonia Foods". With an include list the whole Google list is read, since matches can be anywhere in it.
- Only these sources keeps jobs Google shows via that site or with an apply link to it. Exclude sources drops jobs Google shows via that site, e.g. aggregators you don't want.
- Output: compact leaves out the bullet lists and cuts the description to 500 characters (
descriptionTruncated: true). Rows got about 77% smaller in tests (9.7 KB to 2.2 KB), handy for spreadsheets and AI agents. Salary is still read from the full text first. - Maximum jobs in total caps the whole run.
What the filters returned in test runs:
- Part-time jobs from the last week (Houston): 33 jobs, all part-time and 7 days old or less. 9 jobs labelled full-time only were dropped and not charged.
- Full-time jobs from the last week (Mexico City, Spanish filters): 25 of 25 matched.
- Remote jobs from the last 3 days: 60 of 60 matched.
- Three Chicago hospitals as "Only these companies": the whole list of 81 nursing jobs was read and the 6 from those employers were saved.
Only new jobs, for daily schedules
Turn on Only new jobs and schedule the Actor. Each run remembers the jobs it saved and later runs skip them.
{"queries": ["registered nurse"],"locations": ["Dallas"],"datePosted": "3days","maxJobsPerQuery": 150,"onlyNewJobs": true}
- The memory is a key-value store in your own Apify account (
google-jobs-history-…), one per set of queries and filters. Give several schedules the same History name to share one memory. Jobs are remembered for a year; Forget saved jobs starts over. - The browser keeps scrolling past jobs you already have, until it finds
maxJobsPerQuerynew ones or Google's list ends. A recent Date posted filter keeps that list short. - Don't run two schedules with the same memory at the same time: the one that finishes last would overwrite what the other remembered.
In a test, two runs of the search above half an hour apart saved 89 jobs, then skipped the 71 already delivered and saved 15. Google's list is not identical from one search to the next, so "new" means new to you: some of those 15 had been posted 3 days earlier and simply weren't in the first run's list.
How it works, and how many jobs per search
Google shows Jobs results 10 at a time and loads more as you scroll; there are no numbered pages.
- The first 10 jobs of each query come from a single request through Apify's Google SERP proxy.
- More than 10: a real Chrome browser opens Google, searches, opens the Jobs tab and scrolls until it has what you asked for or Google stops adding jobs. If Google blocks it, it tries up to two more times from other IPs; if those fail too, the query keeps its first 10 jobs and is marked
PARTIAL.
Measured in test runs (October 2026):
| Search | Asked for | Got | Note |
|---|---|---|---|
| registered nurse + software engineer, Chicago | 50 each | 100 | 57 s for both |
| desenvolvedor + analista de dados, São Paulo | 40 each | 80 | 84 s for both |
| nurse, London | 150 | 91 | Google's list ended at 91 |
| data analyst, London | 150 | 94 | Google's list ended at 94 |
A volume test of 40 US searches (10 occupations × 4 cities, 20 jobs each) took 15 minutes. The first 10 jobs came back for all 40 on the first try (median 23 s, slowest 64 s). Scrolling got everything asked for, or everything Google listed, for 36 of the 39 searches that needed it; the other 3 kept their first 10. Since then a second retry from another IP was added, and the 5 searches tested afterwards all completed.
Expect about 90–100 jobs at most per search, because that is where Google stops adding to the list, and 20 seconds to 2 minutes of scrolling per query.
Salary, also when Google doesn't show one
Google labels a salary on only part of the postings, while many others state the pay in their text ("Pay Range $110,000.00 - $135,000.00", "Salary: £30.80 - £35.20 per hour"). When Google shows no salary, the Actor reads it from the posting and marks it salarySource: "description". It only takes an amount with a currency and a pay word or period next to it. It skips money that is something else (company revenue, bonuses, allowances, budgets, tips), and checks that the size fits the period.
Measured on 1,385 jobs from the test runs:
| Salary from Google alone | With salaries read from the text | |
|---|---|---|
| US | 40% | 63% |
| UK | 55% | 68% |
| Brazil, Mexico | 13%, 36% | unchanged: those postings rarely state an amount |
As an accuracy check, the same reader ran on jobs that do have a Google salary. Where it found an amount (310 jobs), 284 (92%) matched Google's: same period, overlapping range. Most of the others are Google converting an hourly rate to a yearly one, or showing a different band than the text. Filter on salarySource if you only want Google's.
Output example
Values below are illustrative, not a real posting.
{"jobId": "AbCdEfGhIjKlMnOpAAAAAA==","title": "Registered Nurse - Medical/Surgical","companyName": "Example Health","location": "Chicago, IL","via": "LinkedIn","postedText": "3 days ago","postedDaysAgo": 3,"postedAtApprox": "2026-10-20","salaryText": "$38.20–$57.30 an hour","salaryMin": 38.2,"salaryMax": 57.3,"salaryCurrency": "USD","salaryPeriod": "HOUR","salarySource": "google","employmentType": "Full-time","employmentTypes": ["FULL_TIME"],"workFromHome": false,"tags": ["Health insurance", "Dental insurance", "Paid time off"],"qualifications": ["Current RN license in Illinois", "BLS certification"],"benefits": ["Tuition reimbursement", "403(b) with match"],"responsibilities": ["Assess and monitor patients", "Administer medications"],"highlights": [{ "title": "Qualifications", "items": ["Current RN license in Illinois", "BLS certification"] }],"description": "Example Health is hiring a Registered Nurse for our Medical/Surgical unit…\n\nWhat you will do\n• Assess and monitor patients…","applyLinks": [{ "title": "Apply on LinkedIn", "url": "https://www.linkedin.com/jobs/view/example-4400000000", "domain": "linkedin.com" },{ "title": "Apply on Example Health Careers", "url": "https://careers.example-health.org/jobs/12345", "domain": "careers.example-health.org" }],"companyLogoUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:…","googleJobsUrl": "https://www.google.com/search?ibp=htl;jobs&q=registered%20nurse&htidocid=AbCdEfGhIjKlMnOpAAAAAA%3D%3D","query": "registered nurse","searchLocation": "Chicago, IL","country": "us","language": "en","position": 4,"source": "browser","scrapedAt": "2026-10-23T12:00:00.000Z"}
The dataset's Overview view shows the main columns side by side.
Use it from the API, schedules and AI agents
Call the Actor from your code with Apify's client libraries. In Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("roomy_tweet/google-jobs-scraper").call(run_input={"queries": ["data analyst"],"locations": ["Austin, TX"],"datePosted": "week","maxJobsPerQuery": 30,})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["companyName"], job["salaryMin"], job["applyLinks"][0]["url"])
In JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('roomy_tweet/google-jobs-scraper').call({ queries: ['data analyst'], locations: ['Austin, TX'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
- Schedules: run it daily or hourly from Apify Console with Only new jobs on.
- Integrations: send results to Google Sheets, Slack, Zapier, Make or your own webhook when a run finishes.
- AI agents: available through Apify's MCP server like any Apify Actor; use the compact output to keep responses small.
Run report and quality check
Each run saves a REPORT record in its key-value store with one line per query: jobs wanted and saved, how the first page and the scrolling went, the exact search text used, and a status:
| Status | Meaning |
|---|---|
OK | Got the number of jobs you asked for |
ALL_AVAILABLE | Google listed fewer jobs than you asked for, and you got all of them |
PARTIAL | Scrolling was blocked or ran out of time; you got what was loaded (at least the first 10 when the first request worked) |
NO_NEW_JOBS | With Only new jobs: every job Google listed was already delivered by an earlier run |
NO_MATCHES | Google listed jobs, but none passed your filters; nothing is charged |
NO_RESULTS | Google has no jobs for this query |
FAILED | Nothing could be loaded |
SKIPPED | A run limit (total jobs, duration or your spending limit) was reached first |
Every run also checks its own quality (REPORT.health, REPORT.qualityProblems, and a warning in the status line). It flags job listings Google showed but that could not be read, the usual sign of a Google layout change. A page like that is never reported as "no results". It also flags more than 20% of saved jobs missing a core field, every search failing, and scrolling stuck at 10 jobs everywhere. Turn on Fail the run if quality drops for scheduled runs, so Apify's failed-run notification tells you. The Actor is checked this way every day by its author.
Good to know
- Maximum per search is about 90–100 jobs, Google's own limit. For more, split a broad search into narrower ones (by city, seniority or specialty); duplicates between them are removed and not charged.
- Salary fields:
salaryMinandsalaryMaxare equal for a single amount. "Up to £48,000" leavessalaryMinempty, and "from $20/hour" leavessalaryMaxempty. postedAtApproxis the scrape date minus Google's "N days ago"; Google gives no exact timestamp.- Bare queries: Google answers some queries without the word "jobs" (just "pharmacist") with no job results. The Actor then searches again with "jobs" ("vagas", "empleo") added, and the report shows the text it used.
- Countries: full runs tested on Google US, UK, Brazil and Mexico; Spain's result page was checked too. The other countries use the same page format but have not been checked one by one.
- No login, no cookies. Only public Google pages are read.
FAQ
How much does it cost? $3.00 per 1,000 jobs, proxies included. Repeats, filtered-out jobs and (with Only new jobs) jobs already delivered are free. See Pricing.
How fast is it? The first 10 jobs of a query take 1 to 65 seconds, typically about 20. Scrolling for more takes 20 seconds to 2 minutes per query, and two queries scroll at the same time with the default 4 GB of memory. 40 queries of 20 jobs took 15 minutes.
Do I need proxies or a Google account? No. Proxies are included and no login is used.
Which countries and languages? 30 countries, including the US, UK, Canada, Australia, India, Germany, France, Brazil, Mexico and Spain. Google's labels are read in English, Portuguese and Spanish; other countries are searched locally with the English interface.
Why do some jobs have no salary? Neither Google nor the posting text states one. See Salary for how often each does.
Does it return recruiter e-mails or phone numbers? No. It returns what Google Jobs shows: the posting, the company and the apply links.
Why did a query return exactly 10 jobs? Either you asked for 10, or scrolling was blocked twice: its status in REPORT is then PARTIAL.
Can I monitor new postings every day? Yes: turn on Only new jobs and schedule the Actor. Jobs already delivered are skipped and not charged.
Is it legal to scrape Google Jobs? The Actor reads publicly available job postings only. Postings can still contain personal data, such as a recruiter's name, so check that your use complies with the laws that apply to you, such as the GDPR, and consult a lawyer if in doubt.