How to use it: 3 steps
- Make a free Apify accountApify is the cloud platform where our tools run. The free plan gives you $5 of usage every month, no credit card needed. You pay Apify, not us.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
python developerin Job searches. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
Google Jobs Scraper searches Google Jobs for your job titles and a location and returns one row per job: title, company, location, salary, job type, posting age, full description and the apply links to LinkedIn, Indeed or the employer site. It reads the public Google Jobs results page, so you need no Google login and no API key. The default input (python developer in Berlin, 10 jobs) usually takes 10–60 seconds and costs $0.033.
- You add one or more job searches, for example
python developerorregistered nurse, and a location. - The Actor opens the Google Jobs results page for each search in the right Google country.
- It reads every job card: title, company, location, the site Google found the job on (
via), posting age, salary and job type. - It reads the job panel too: the full description, Google's highlights and all apply links, without tracking parameters.
- It removes duplicate jobs (same Google job id) and saves one Dataset row per job.
- Fast mode reads one Google page per search, about 10 jobs. Deep mode repeats each search with Google's date and job-type filters and removes duplicates, so you get several times more jobs.
Good for
- Job market research: who hires for a role in a city, and on which job boards.
- Lead lists for recruiters and staffing agencies: companies with open roles, with the link to each job.
- Salary checks: Google's salary text where the job has one.
- A daily job feed for a niche job board, a Slack channel or a spreadsheet.
Not a good fit
- 8 countries only: United States, United Kingdom, Canada, India, Germany, France, Spain and Brazil (
countryCode). Google shows the texts in the language of that country, for examplevor 1 TagandVollzeitin Germany. - Google shows about 10 jobs per search page. Fast mode gives about 10 jobs per search; deep mode about 20–70 (our tests). For more jobs, add more searches (up to 50) or more specific titles.
salaryis oftennull: Google shows a salary only for some jobs (0–40 % in our tests).highlightsis oftennullin fast mode: Google does not send this block on many pages. The fulldescriptionis still there.- No recruiter names, emails or phone numbers. The Actor saves only the public job post.
- Google decides which jobs it shows. Two runs a few minutes apart can return a slightly different set or order.
- Google's terms do not allow automated access to Google Search. You are responsible for how you use the data.
Who uses it
Recruiters and agencies
Find companies that hire for a role in your city right now.
Job board owners
Fill a niche job board or a daily feed with fresh jobs.
Market researchers
See which job sites carry the jobs for a role and a place.
Price
Pay per event: you pay for each result the tool saves, plus a small start fee for each run. The price includes Apify platform costs. Apify bills you, not us. Prices below are for the Apify free plan.
| What you pay for | Price | When |
|---|---|---|
| Start fee | $0.01 | Charged once per run. This tool uses 1 GB of memory or less by default; more memory costs more. |
| Google Jobs search page | $0.013 | One Google Jobs results page that Google answered (up to 10 jobs), including pages with no jobs. Pages that failed are not charged. |
| Job listing | $0.001 (from $0.00085 on paid Apify plans) | One unique job saved to the Dataset. Duplicates, not_found and error rows are free. |
Examples
- One result: about $0.01.
- 1,000 results: about $1.01.
- Every day 100 results, for 30 days: about $3.30 a month.
Free to try: the Apify free plan gives you $5 of usage every month, no credit card needed. That is enough for about 4,900 results.
Prices checked on 24 October 2026. See the current price on Apify.
Questions
Can I scrape Google Jobs without a Google account?
Yes. The tool reads the public Google Jobs page. You need no login, cookies or API key.
Which countries can I search?
Eight countries: the US, UK, Canada, India, Germany, France, Spain and Brazil.
How many jobs do I get per search?
Fast mode gives about 10 jobs per search. Deep mode gave about 20 to 70 in tests.
Why do many jobs have no salary?
Google shows a salary only when the job post has one. The tool never guesses a salary.
Do I need a Google account or API key?
No. The Actor reads the public Google Jobs results page without login, cookies or keys.
Is this the official Google Jobs API?
No. Google has no public API for Google Jobs search results. This Actor is not made by or linked to Google.
Why are some texts in German or French?
Google shows jobs in the language of the country you search. Search in Germany, and postedAt says vor 2 Tagen and employmentType says Vollzeit. postedAtApprox gives a date that is the same in every language.
Why is salary empty for most jobs?
Google shows a salary only when the job post or job board gives one. The Actor does not guess: no salary on Google means salary: null.
Can I get the recruiter's email or phone?
No. The Actor saves only the public job post and does not collect personal contact data.
Details
Step by step on Apify
- Open the Input tab.
- In Job searches (
queries), keeppython developeror add your own job title. - Keep Location
Berlinand Max jobs10, or change them. Countryautopicks the country from the location. - Click Start.
- Open the Output tab. The Jobs table shows
title,company,location,salaryand the apply links.
Use cases
| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Job market research | queries + location, mode: "deep" | Job | title, company, via, postedAt | CSV or Excel export |
| Recruiting lead list | queries like "sales manager" + datePosted: "week" | Job | company, title, location, applyLinks | Google Sheets or CRM through Apify integrations |
| Salary check | queries + location | Job | salary, employmentType, title | Spreadsheet |
| Daily job feed | queries + datePosted: "today" on a schedule | Job | jobId, title, googleJobsUrl | Slack, email or a website through webhooks |
Tips for better results
- Use deep mode when one search gives too few jobs. It finds several times more.
- Add more specific titles, like "junior python developer", to get more unique jobs.
- Use postedAtApprox to sort by date. It works the same in every language.
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"status": "complete",
"title": "Python Team Lead, Integration team",
"company": "Fliff Inc",
"location": "Beliebiger Ort",
"via": "LinkedIn",
"postedAt": "vor 1 Tag",
"postedAtApprox": "2026-10-14",
"salary": null,
"employmentType": "Vollzeit",
"workFromHome": true,
"description": "We’re looking for a Python Team Lead to join our Integration team, which owns a broad set of critical integrations across the product…",
"highlights": null,
"applyLinks": [
{ "title": "LinkedIn", "url": "https://de.linkedin.com/jobs/view/python-team-lead-integration-team-at-fliff-inc-4479228357" },
{ "title": "Startup Jobs", "url": "https://startup.jobs/python-team-lead-integration-team-fliff-inc-10437417" }
],
"jobId": "eAHxzL0ATotpbjXSAAAAAA==",
"googleJobsUrl": "https://www.google.de/search?ibp=htl;jobs&q=python+developer+Berlin&htidocid=eAHxzL0ATotpbjXSAAAAAA%3D%3D&hl=de-DE#…",
"position": 2,
"query": "python developer",
"searchLocation": "Berlin",
"countryCode": "de",
"searchVariant": null,
"source": "google_jobs",
"sourceUrl": "https://www.google.de/search?q=python+developer+Berlin&udm=8&hl=de&gl=de",
"fetchedAt": "2026-10-15T06:20:55.335Z",
"statusReason": null,
"errorCode": null
}Use it from code
Actor ID: cliqtomedia/google-jobs-scraper. You need your Apify API token from Apify Console → Settings → API & Integrations.
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("cliqtomedia/google-jobs-scraper").call(run_input={
"queries": [
"python developer"
],
"location": "Berlin"
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)curl -X POST "https://api.apify.com/v2/acts/cliqtomedia~google-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"queries": ["python developer"], "location": "Berlin"}'# pip install langchain-apify
# set APIFY_TOKEN in your environment
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("cliqtomedia/google-jobs-scraper")
result = tool.invoke({"run_input": {"queries": ["python developer"], "location": "Berlin"}})
print(result)The cURL call waits for the results, up to 300 seconds. For longer runs, start a run (/runs) and get the results with a webhook or by checking the run. Apify API docs. LlamaIndex, MCP for AI agents and the JavaScript client: AI agents & MCP.
Data fields (25)
| Field | Type | Meaning |
|---|---|---|
status | string | complete: a job; partial: a deep search where some Google pages did not answer (jobs of the other pages are in their own rows); not_found: Google has no jobs for this search; error: Google did not answer. |
title | string | Job title as the employer wrote it. |
company | string | Employer name. |
location | string | Job location as Google shows it, e.g. "Berlin, Germany" or "Anywhere". |
via | string | Site Google found the job on, e.g. "LinkedIn" or "via Indeed". |
postedAt | string | Posting age as Google shows it, e.g. "2 days ago" or "vor 1 Tag"; null when Google does not show it. |
postedAtApprox | string | Approximate posting date (YYYY-MM-DD) = fetchedAt minus postedAt; null for open ranges such as "30+ days ago". |
salary | string | Salary as Google shows it, e.g. "$104K–$156K a year"; null when the job has no salary (not 0). |
employmentType | string | Job type as Google shows it, e.g. "Full-time" or "Vollzeit". |
workFromHome | boolean | true when Google tags the job as work from home; null when it does not say. |
description | string | Full job description as plain text; null when includeDescription is off. |
highlights | array | Google's job highlights (Qualifications, Responsibilities, Benefits); null when Google shows none or includeDescription is off. |
applyLinks | array | Where to apply: the employer site and job boards, with tracking parameters removed. |
jobId | string | Google's job id; the same job has the same id across searches and runs. |
googleJobsUrl | string | Google Jobs page that opens this job. |
position | integer | Order of the job in this search's results (1 = first, after removing duplicates); null on status rows. |
query | string | Your job search. |
searchLocation | string | Location from your input; null when empty. |
countryCode | string | Google country searched (us, gb, ca, in, de, fr, es, br). |
searchVariant | string | Deep mode: which search found the job (base, datePosted:week, employmentType:parttime…); null in fast mode. |
source | string | Always google_jobs. |
sourceUrl | string | Google search URL that was fetched. |
fetchedAt | string | When the page was fetched (ISO 8601, UTC). |
statusReason | string | Why the row is partial, not_found or error; null on complete rows. |
errorCode | string | Machine-readable error code on error rows, e.g. SOURCE_TIMEOUT; null otherwise. |
Input settings (8)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| Job searches required | queries | array | ["python developer"] |
| Location | location | string | "Berlin" |
| Country | countryCode | string | "auto" |
| Date posted | datePosted | string | "any" |
| Job type | employmentType | string | "any" |
| Search depth | mode | string | "fast" |
| Max jobs | maxJobs | integer | 10 |
| Include description | includeDescription | boolean | true |


