Google Jobs Scraper
Pricing
from $28.00 / 1,000 results pages
Google Jobs Scraper
Search Google Jobs by keyword, location and country. Get structured job postings with parsed salary, posted date, job type and work mode. Pay per results page; empty searches are free.
Pricing
from $28.00 / 1,000 results pages
Rating
0.0
(0)
Developer
krammer liu
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
40 minutes ago
Last modified
Categories
Features
Share
Search Google Jobs results by keyword, location and country, and get clean, structured job postings in an Apify dataset. You pay per Google results page fetched: $0.028 to $0.09 per results page (up to 10 jobs), depending on your Apify plan. Searches that return nothing are free.
What it does
Give it one or more search queries (and optionally locations). It runs every query and location pair as a separate Google Jobs search and delivers the postings as dataset items.
- Searches Google Jobs results for 4 countries: United States, United Kingdom, India, Germany.
- Returns title, company, location, full description, highlights, benefits, apply links and the raw salary, job type and posted text.
- Adds structured fields parsed from the text: salary min/max/currency/period, posted date, employment types and work mode (remote or hybrid).
- Filters by posting date and employment type, and can add the word "remote" to every search.
- Removes duplicate postings inside one run and skips postings that have no title or company.
- Charges once per Google results page (up to 10 jobs); searches with no results are free.
Use cases
- Salary research. Search one role in several cities and compare
salaryMin,salaryMax,salaryCurrencyandsalaryPeriod. Only postings where Google shows a salary have these fields. - Find companies that are hiring. Search a role and a city, then group the results by
company. Recruiters and sales teams can use this list to see who is hiring for what, and where. - Daily job alerts. Run the Actor on an Apify schedule with
datePostedset to7d, and keep thejob_idvalues you have already seen so you can drop them on your side (runs do not share duplicate memory).7dplus your ownjob_idlist gives you only new jobs and keeps more results per page than24h: Google returns its most relevant jobs first, and in a busy search often only a few of them are from the last 24 hours. - Daily job hunt with an AI assistant. The examples repo has Python scripts and a Claude Code skill that scores new jobs against your resume and lists the ones to apply to. You still apply yourself.
- Feed a job board or a spreadsheet. Every item has the same fields, so you can export the dataset or read it with the API and load it into your own database.
- Give an AI agent live job data. Agents can call the Actor through the Apify API or the Apify MCP server. See Use with AI agents and the API.
How to get started
- Click Try for free (or Start) on this page. You need an Apify account; the Free plan works.
- Enter one or more search queries, for example
software engineer. - Optional: add locations, choose a country, and set
datePosted,jobTypesormaxResultsPerSearch. - Click Start. A search for 100 jobs usually finishes in less than a minute.
- Open the Output tab to see the jobs. Export them as JSON, CSV or Excel, or read them with the API.
- To repeat the search automatically, create a schedule for the Actor in Apify Console.
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
queries | array of strings | yes | ["software engineer"] in the Console | 1 to 20 search queries. Each query is searched separately with every location. |
locations | array of strings | no | [] | 0 to 20 cities or regions, for example "New York, NY". Leave empty to search the whole country. |
country | string | no | us | One of us, gb, in, de. |
language | string | no | empty (chosen from the country) | One of en, de, hi, or empty. Empty means en for us, gb, in and de for de. |
datePosted | string | no | any | One of any, 24h, 3d, 7d, 30d. Jobs with no posting time are kept. |
maxResultsPerSearch | integer | no | 100 | 1 to 200. Upper limit of delivered jobs for each query and location pair. |
jobTypes | array of strings | no | [] | Any of FULLTIME, PARTTIME, CONTRACTOR, INTERN. Empty means no filter. |
remoteOnly | boolean | no | false | When true, the word "remote" is added to the text of every search. |
The number of searches is the number of queries times the number of locations (at least 1). It must not exceed 100, or the run fails at start with a message that says so.
Example input:
{"queries": ["software engineer", "data analyst"],"locations": ["New York, NY", "Austin, TX"],"country": "us","datePosted": "7d","jobTypes": ["FULLTIME"],"maxResultsPerSearch": 50}
Output
Each dataset item is one job posting.
| Field | Type | Description |
|---|---|---|
job_id | string | Google's identifier of the posting. Used to remove duplicates inside a run. |
title | string | Job title. |
company | string | Company name. |
location | string or null | Location text as shown by Google. |
description | string or null | Full description text. |
highlights | array or null | Sections such as qualifications and responsibilities: [{ "title", "items": [...] }]. |
apply_options | array or null | Places to apply: [{ "title", "link" }]. |
salary | string or null | Salary text as shown by Google. |
benefits | array of strings or null | Benefit labels, when Google shows them. |
job_type | string or null | Employment type text as shown by Google. |
posted | string or null | Posted text as shown by Google, for example "3 days ago". |
page | integer or null | Result page the posting was found on. |
searchQuery | string | The query that found the posting. |
searchLocation | string or null | The location that found the posting, or null if none was set. |
country | string | The country code used for the search. |
salaryMin, salaryMax | number or null | Salary range parsed from salary. Same value when there is one number. |
salaryCurrency | string or null | ISO 4217 code (USD, GBP, EUR, INR). Null when the currency is unclear. |
salaryPeriod | string or null | hour, day, week, month or year. |
postedDate | string or null | YYYY-MM-DD (UTC): run start time minus the relative time in posted. |
postedHoursAgo | integer or null | The same relative time in hours (a month counts as 30 days). |
jobTypes | array or null | Subset of FULLTIME, PARTTIME, CONTRACTOR, INTERN. |
workMode | string or null | remote or hybrid when the title or location says so; otherwise null (null does not mean on-site). |
A field is null when Google does not show it. The structured fields are parsed from English and German text only; for other text they are null.
Example item (abridged, company name replaced):
{"job_id": "RtLv7vlPTbn2E40SAAAAAA==","title": "Staff Software Engineer - Card Technology","company": "Example Corp","location": "New York, NY (+3 others)","description": "Example Corp is hiring a Staff Software Engineer for its card technology team. ...","highlights": [{ "title": "Qualifications", "items": ["8+ years of software engineering experience"] }],"apply_options": [{ "title": "Example Corp Careers", "link": "https://careers.example.com/jobs/12345" }],"salary": "$150K–$200K a year","benefits": ["Health insurance"],"job_type": "Full-time","posted": "3 days ago","page": 1,"searchQuery": "software engineer","searchLocation": "New York, NY","country": "us","salaryMin": 150000,"salaryMax": 200000,"salaryCurrency": "USD","salaryPeriod": "year","postedDate": "2026-11-05","postedHoursAgo": 72,"jobTypes": ["FULLTIME"],"workMode": null}
Supported countries
| Code | Country | Languages | Default language |
|---|---|---|---|
us | United States | en | en |
gb | United Kingdom | en | en |
in | India | en, hi | en |
de | Germany | de, en | de |
A language that is not in the list for the chosen country is still searched, with a warning in the log that results may be sparse. A country outside this list fails the run at start.
Use with AI agents and the API
Python, with the apify-client package:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("krammer/google-jobs-scraper").call(run_input={"queries": ["machine learning engineer"],"locations": ["Berlin"],"country": "de","language": "en","datePosted": "7d","maxResultsPerSearch": 30,})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], "|", job["company"], "|", job["salaryMin"], job["salaryCurrency"])
curl (starts the run, waits for it to finish and returns the dataset items; for large inputs use the asynchronous run endpoint instead):
curl -X POST "https://api.apify.com/v2/acts/krammer~google-jobs-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"queries": ["registered nurse"], "locations": ["Chicago, IL"], "maxResultsPerSearch": 20}'
Every input field has a description written for AI agents, so tools that read the input schema (for example the Apify MCP server) can read what each field is for.
Limits
- Each search delivers at most
maxResultsPerSearchjobs (1 to 200, default 100). - At most 100 searches per run (queries x locations), at most 20 queries and 20 locations.
- The number of results depends on what Google shows for the query. A search can return fewer jobs than the maximum.
- If you set a maximum total charge for the run, the run stops when it is reached and keeps the jobs already delivered.
FAQ
Why did I get fewer jobs than maxResultsPerSearch?
Google may have fewer postings for that query. Also, the datePosted and jobTypes filters are applied to the results Google returns; the Actor does not fetch extra results to make up for removed ones. Duplicates and postings without a title or company are removed too.
Am I charged when a search returns nothing? No. A results page is charged only if it contains at least one job posting with a title and company. If Google returns no results, nothing is charged. Pages whose jobs are all removed by your filters, or were all delivered by an earlier search in the same run, are still charged, because those pages were fetched. The log explains why a search delivered nothing.
What counts as a duplicate?
Postings with the same job_id inside one run. The first one is kept and later ones are dropped from the dataset. Billing is per results page, so the page that contained a duplicate is still charged. Runs do not share this memory, so a later run delivers the same posting again.
How do the filters work?
datePosted keeps jobs whose postedHoursAgo is within 24 hours, 3 days, 7 days or 30 days. jobTypes keeps jobs whose jobTypes has at least one of the types you list. If Google does not show the posting time of a job, the job is kept (postedHoursAgo is null). If Google does not show the type of a job, the job is removed when jobTypes is set.
Does remoteOnly remove on-site jobs?
No. It adds the word "remote" to the search text, so the search asks for remote jobs, but the results are not filtered. Use the workMode field of the output if you need to check each job.
Billing and failures
- You are charged once for each Google results page fetched that contains at least one valid job posting: $0.028 to $0.09 per results page (up to 10 jobs), depending on your Apify plan (Free plan $0.09, Starter $0.036, Scale $0.032, Business $0.028).
- You are not charged for searches with no results, pages with only invalid jobs (missing title or company), or searches that failed.
- Pages are charged even if all their jobs were removed by your filters or were duplicates of an earlier search in the run.
- If some searches fail, the run still finishes as SUCCEEDED. The status message says so, for example "Partially completed: 12 jobs delivered; 1 of 3 searches failed (...)". Result pages that were fetched are charged; failed searches are not. If no search could be fetched at all, the run is FAILED and nothing is charged.
- The
RUN_SUMMARYrecord in the default key-value store lists the outcome, the number of jobs, the failure reasons and the request ids of failed searches. - If the platform migrates your run to another server, the last batch of jobs may be sent again once. This is a known window.
- Free Apify plans have a monthly allowance for this Actor. The allowance counts every result retrieved for your searches, including duplicates and jobs removed by your filters, because those results are still fetched. When it is used up, the run stops, nothing more is charged, and the status message shows the amount used. Paid Apify plans are not limited. The allowance resets at the start of each month (UTC).