Google Jobs Scraper — Job Listings, Salaries & Apply Links
Pricing
from $1.50 / 1,000 unique job delivereds
Google Jobs Scraper — Job Listings, Salaries & Apply Links
Scrape Google Jobs listings for nursing, warehouse, driver and data entry roles. Get salary ranges, posting dates and direct apply links. Empty searches are free.
Pricing
from $1.50 / 1,000 unique job delivereds
Rating
0.0
(0)
Developer
Bruno Aguilera Silva
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
Google Jobs Scraper — Job Listings, Salaries & Apply Links
Scrape Google Jobs listings for nursing, warehouse, driver, data entry and other roles. Export job titles, companies, locations, normalized salary ranges, real posting dates and direct apply links to JSON, CSV or Excel. Search the US, UK, Canada, Europe, India and Latin America with local queries.
Google provides an excerpt rather than the full description for some listings; descriptionIsTruncated flags those cases. Salary and posting-date fields remain null when the listing does not provide them.
Search many roles across many locations in one run, get each job once even when several searches find it, and schedule daily runs that return only jobs you haven't seen before.
$2.00 per 1,000 jobs ($1.50 on paid Apify plans). Searches that find nothing are never charged.
Why this scraper
- No surprises on your bill. You pay per unique job delivered. Empty searches, duplicates and internal retries are free.
- Every search is accounted for. Each run adds one summary row per search with its status (
ok,empty,unsupported_country,blocked,error,skipped). Searches left unexecuted by a job, charge or request limit are markedskipped, with the stop reason and pending count. - Bulk search in one run. Give it a list of queries and a list of locations and it searches every combination.
- Salaries you can sort. Google shows pay as free text ("$45–60 hourly", "€50K a year"). This actor parses it into minimum, maximum, currency and period, plus an annualized estimate so hourly and yearly offers can be compared. Explicit currency codes and regional magnitudes such as lakh, crore, 万, juta and triệu are preserved and normalized where unambiguous; unavailable or ambiguous information stays null.
- Real dates. "3 days ago" becomes
"2026-10-15". - No duplicates. A job found by several searches appears once, with a
foundBylist of every search that matched it. - Only new jobs, on a schedule. Turn on
onlyNewJobsand each run returns just the listings that appeared since the last one. You only pay for those. - Drop-in compatible. Inputs and outputs also accept the field names used by other popular Google Jobs tools (
query,location,posted_within,apply_options,detected_extensions…), so switching takes minutes.
Use cases
- Job boards and aggregators: feed fresh listings into your site or app every day.
- Salary benchmarking: compare pay for a role across cities and companies.
- Recruiting and sales intelligence: see which companies are hiring for which roles, and where.
- Labor market research: track demand for skills and roles over time.
- AI agents: give an assistant a live job search tool through the Apify MCP server.
Ready-made job searches
Start with a small, editable example: each profile searches one city and delivers up to ten jobs. Salaries are included when advertised.
| Market | Example |
|---|---|
| United States | Nursing jobs in Texas with salaries |
| United Kingdom | Warehouse jobs in the UK |
| Germany | Nursing jobs in Germany |
| India | Data entry jobs in India |
| Brazil | Driver jobs in Brazil |
| México | Trabajo de chofer en Ciudad de México |
| Canada | Nursing jobs in Canada |
| France | Driver jobs in France |
| España | Trabajo de administrativo en España |
| Chile | Trabajo de conductor en Chile |
Quick start
{"queries": ["Data Engineer", "Analytics Engineer"],"locations": ["New York, NY", "Austin, TX"],"country": "us","postedWithin": "week","maxJobsPerSearch": 50}
This runs four searches (2 queries × 2 locations) and returns every unique job found.
Input
| Field | Type | Default | Description |
|---|---|---|---|
queries | string[] | ["software engineer"] | Roles or keywords, e.g. ["Data Engineer", "Registered Nurse"]. If omitted, the actor uses the prefilled search; an explicit empty list is invalid. Job-title style queries work best. |
locations | string[] | [] | Cities or regions, e.g. ["Austin, TX", "London"]. Every query is searched in every location. A city gives the best results. |
country | enum | us | Country the search targets. Only countries where Google Jobs serves listings can be selected. |
language | string | auto | Best left empty: the actor uses the language that matches the country. Forcing English in non-English countries often returns nothing. |
postedWithin | enum | any | today, 3days, week, month or any. today searches a three-day candidate window, then keeps only jobs with a known posting time within 24 hours. Jobs without a posting date are excluded from today results. |
employmentTypes | enum[] | [] | FULLTIME, PARTTIME, CONTRACTOR, INTERN. Adds schedule keywords to the query and filters the results. Jobs without a published type are kept; a warning explains when the filter excludes more than 40% of candidates. |
remoteOnly | boolean | false | Only remote jobs. |
maxJobsPerSearch | integer | 50 | Maximum unique jobs per query/location combination. Google currently exposes about 10 per initial search; use expandSearch for more. |
maxJobs | integer | 200 | Maximum jobs for the whole run. |
maxSearchRequests | integer | 100 | Total HTTP request cap, including retries and expansion (1–10,000). Stops with an explicit message and skipped summaries. Increase deliberately for larger batches. |
expandSearch | boolean | false | When a search is saturated, automatically run narrower variations (date windows, job types) to find more unique jobs. |
onlyNewJobs | boolean | false | Skip jobs delivered by previous runs with the same searches. |
stateKey | string | auto | Name of the memory used by onlyNewJobs. Set it to share or separate memory between tasks. |
includeSearchSummaries | boolean | true | Add one summary row per search. |
outputFormat | enum | both | normalized, serpapi_compatible or both. |
Output
One item per unique job (type: "job"):
{"type": "job","jobId": "uxZzDPHtdB_zAAAAAAAAAA==","title": "Senior Data Engineer","companyName": "Northwind Analytics","location": "Austin, TX","via": "LinkedIn","isRemote": false,"scheduleType": "Full-time","employmentType": "FULLTIME","postedAt": "2026-10-15","postedAtRaw": "3 days ago","postedAtPrecision": "day","salary": {"raw": "$140K–$175K a year","min": 140000,"max": 175000,"currency": "USD","period": "year","annualMin": 140000,"annualMax": 175000},"applyOptions": [{ "title": "Northwind Careers", "url": "https://careers.example.com/jobs/1234", "domain": "careers.example.com", "isDirect": true },{ "title": "LinkedIn", "url": "https://www.linkedin.com/jobs/view/...", "domain": "linkedin.com", "isDirect": false }],"highlights": {"qualifications": ["5+ years building data pipelines", "Strong SQL and Python"],"responsibilities": ["Own the ingestion layer"],"benefits": ["Health insurance", "401(k) matching"]},"description": "Northwind Analytics is looking for a Senior Data Engineer to...","descriptionIsTruncated": true,"shareLink": "https://www.google.com/search?ibp=htl;jobs&q=...&htidocid=...","foundBy": [{ "query": "Data Engineer", "location": "Austin, TX", "variant": null }],"applyDomains": ["careers.example.com", "linkedin.com"],"firstSeenAt": null,"searchUrl": "http://www.google.com/search?q=Data+Engineer+in+Austin%2C+TX&udm=8&gl=us&hl=en","country": "us","language": "en","scrapedAt": "2026-10-18T03:12:44Z"}
One summary row per search (type: "search_summary"):
{"type": "search_summary","query": "Data Engineer","location": "Austin, TX","variant": null,"country": "us","language": "en","status": "ok","jobsFound": 10,"newJobs": 7,"duplicates": 3,"skippedSeen": 0,"skippedUncertain": 0,"attempts": 1,"searchUrl": "http://www.google.com/search?q=Data+Engineer+in+Austin%2C+TX&udm=8&gl=us&hl=en","message": null,"stopReason": null,"unexecutedSearches": 0}
Not every posting publishes every field. Google shows a salary for only part of the listings, and that share varies a lot by country and role. If the salary text omits a currency, the actor uses the selected country's known currency; when the country has no reliable mapping, currency stays null. A bare dollar sign is never relabeled as euros, pounds, yen or reais. Explicit source codes, including a historical code published by Google, are retained without currency conversion. Other unpublished fields stay null. Regional salary magnitudes include Indian lakh/lac/L and crore/Cr, Japanese 万/億, and German Tsd./Mio.; explicit currency codes take precedence over the search country.
If a limit stops the run, its status and summary messages say stopped: maxJobs reached, stopped: max charge reached or stopped: max search requests reached and count searches not executed. Date, remote and employment filters also write warnings into the affected search summary when they exclude more than 40% of candidates.
Pricing
| Event | Free plan | Paid plans |
|---|---|---|
| Unique job delivered | $0.002 | $0.0015 |
| Jobs | Cost (free plan) | Cost (paid plans) |
|---|---|---|
| 100 | $0.20 | $0.15 |
| 1,000 | $2.00 | $1.50 |
| 10,000 | $20.00 | $15.00 |
Not charged: empty searches, unsupported countries, duplicates, jobs skipped by onlyNewJobs, retries. Set a maximum cost in the run options and a request cap with maxSearchRequests. The actor checks event capacity before delivery and records its stop reason. Apify’s total limit also includes platform usage; a very low limit can abort a run before final summaries are saved. In-flight requests can still consume platform resources after a stop is detected.
Localized dates and salary periods
Date badges and salary periods are recognized in every default language used by the country selector: English, Spanish, Portuguese (including Portugal), German, French, Italian, Dutch, Danish, Greek, Indonesian, Japanese, Russian, Chinese, Thai, Vietnamese and Arabic. Italian 4 giorni fa and Dutch 3 dagen geleden are preserved and converted; all’anno, al mese, all’ora, per jaar, per maand and per uur produce normalized salary periods. A per-country regression test checks date extraction and all five salary periods. This language coverage does not guarantee that Google returns listings for every query, or that every listing publishes a date or salary.
Supported countries
The country selector provides 85 search settings. Two live rounds in October 2026 tested every setting with two local role queries per round, including successful listings in the US, UK, Canada, Germany, India, Mexico, Chile, Brazil, Italy and the Netherlands. Availability still depends on the query and Google: a valid empty result does not establish that a country is unavailable.
Use a city and country when place names are ambiguous. Google's country setting influences the search; it is not a strict geographic filter, and remote roles can list other locations.
Our October 2026 Apify tests returned local listings in France and Chile, so both can be selected. Single-query probes on October 20 returned no identifiable Google Jobs cards in Australia, Ireland, New Zealand, Poland, Sweden or South Korea; these countries remain outside the selectable enum. One empty query does not establish nationwide unavailability. Unsupported countries are never charged.
Daily job feeds
- Save your input as a task.
- Turn on
onlyNewJobsand setpostedWithinto3days. - Add a schedule (for example, every day at 07:00).
- Connect the dataset to Google Sheets, a webhook, Make, Zapier or n8n.
The three-day window overlaps daily runs, and onlyNewJobs skips listings already delivered under the same stateKey. Google may return only listings aged 1–3 days for a today search; its strict 24h filter can then deliver zero. today also excludes listings without a posting date. Use 3days for a daily feed to catch later arrivals while avoiding repeat charges.
Privacy and incremental state
Descriptions and highlights are retained after local redaction of recognizable emails, phone numbers and contact clauses. personalDataRedacted: true signals changed content. This is heuristic redaction: arbitrary personal names and unusual contact formats may remain in free text. The actor never extracts recruiter names, emails or phone numbers into dedicated fields. Parser diagnostics store structural counters only; raw HTML is not saved by production runs.
onlyNewJobs retains IDs for 60 days in 16 seen shards plus 16 delivery-reservation shards, with a 100,000-ID combined limit. A full store stops before the next delivery rather than evicting recent IDs. A reservation left by an interrupted delivery is skipped with skippedUncertain and a warning, because its delivery or charge acknowledgement is uncertain. Inspect it before manually retrying; do not erase state as an automatic recovery step.
Runs sharing a stateKey require an exclusive writer lease; overlapping runs fail before searching. Schedule them far enough apart. Cloud leases expire and renew; this is not a transaction spanning Apify storage and billing. A crashed local process can leave a filesystem lock that needs manual cleanup after checking no writer is running.
Only enabled Apify Proxy with the GOOGLE_SERP group is supported. Disabled proxies, custom URLs and other groups fail with configuration instructions before a search.
For AI agents
Add this actor to any MCP client (Claude, Cursor and others):
https://mcp.apify.com?tools=sondalabs/google-jobs-scraper
Keep maxJobs small for interactive use; the default of 200 keeps answers fast and cheap.
FAQ
Why did a search return no jobs?
Check its summary row. empty usually means a descriptive query (use a job title), a country/location mismatch, or a forced language. A valid Google no-results page remains empty even when it includes suggestions or interface widgets; it generates no job charges. If Google returns identifiable job cards but none can be read, the summary explains parser mismatch and affected searches are not charged. A majority of confirmed mismatches makes the run fail, including a single-search run.
Why are some salaries missing? Google only shows salary when the original posting includes it.
How does onlyNewJobs remember what I already have?
It stores the IDs of delivered jobs in a named key-value store in your own Apify account. Nothing is shared between users. Delete that store, or change stateKey, to start over.
Is this an official Google API? No. It is an independent tool, not affiliated with or endorsed by Google. It collects job listings that Google Jobs shows publicly in search results and links back to the original postings.
Support
Open an issue in the Issues tab. Changes to output fields are recorded in the changelog; existing fields keep their meaning.