How to use Google Jobs Scraper
Step by step: in the Apify Store, over the API, from JavaScript or Python, in n8n, and from AI agents through MCP or LangChain.
$8.10 per 1,000 jobs on the Free plan, down to $3.15 on higher plans (live Apify price on 2026-11-03).
1. In the Apify Store (no code)
- Open arcadium/google-jobs and sign in to Apify (a free account works).
- Fill in the input form. The fields below are the ones the example uses.
- Set a maximum cost per run in the run options if you want a hard cap.
- Start the run. Rows appear in the Output tab as they arrive.
- Export the dataset as JSON, CSV or Excel, or connect an integration.
| Input field | Type | Description |
|---|---|---|
queries | array | What to search on Google Jobs, as you would type it, e.g. ["software engineer", "registered nurse", "barista part time"]. Each query runs once per location and gives up to maxResultsPerQuery jobs. |
locations | array | Places to search in, e.g. ["Seattle, WA", "Austin, Texas", "Berlin"]. Each query runs once per location (sent to Google as "<query> in <location>"). Leave empty to let Google pick the area of the country you search in. A city, region or country name works. |
datePosted | string | Only jobs posted within this window, the same filter as Google's own Date posted chip. |
remoteOnly | boolean | Adds Google's Remote filter (work from home jobs). The workFromHome field shows Google's own flag per job. |
maxResultsPerQuery | integer | Jobs per query and location. Google shows 10 per search; above 10 the actor also runs Google's own filter variants (job types and date windows) and merges them without duplicates, so a broad search reaches about 60-150 jobs. Narrow searches stop earlier when Google has no more. |
country | string | Two-letter country code of the Google Jobs market to search, e.g. US, GB, DE, IN, CA. Salaries with a bare $ are labelled with this country's dollar (CAD for CA). |
language | string | Google interface language code, e.g. en, de, fr, es, pt-BR. Labels such as "3 days ago" and "Full-time" come in this language; normalised fields (postedAt, employmentTypes, salary) are filled for en, de, fr, es, it, pt and nl. |
includeDescription | boolean | Adds the full job description text Google shows (emails and phone numbers replaced with [email] and [phone]). Off gives smaller rows at the same price. |
Example input:
{
"queries": [
"software engineer"
],
"locations": [
"Seattle, WA"
],
"datePosted": "any",
"remoteOnly": false,
"maxResultsPerQuery": 10,
"country": "US",
"language": "en",
"includeDescription": true
}
2. Over the Apify API
The synchronous endpoint runs the actor and returns its rows in one call (for runs up to about five minutes; use the asynchronous run endpoint for longer ones).
curl -X POST "https://api.apify.com/v2/acts/arcadium~google-jobs/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"queries":["software engineer"],"locations":["Seattle, WA"],"datePosted":"any","remoteOnly":false,"maxResultsPerQuery":10,"country":"US","language":"en","includeDescription":true}'
3. From JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/google-jobs').call({
"queries": [
"software engineer"
],
"locations": [
"Seattle, WA"
],
"datePosted": "any",
"remoteOnly": false,
"maxResultsPerQuery": 10,
"country": "US",
"language": "en",
"includeDescription": true
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
4. From Python
# pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/google-jobs").call(run_input={
"queries": ["software engineer"],
"locations": ["Seattle, WA"],
"datePosted": "any",
"remoteOnly": False,
"maxResultsPerQuery": 10,
"country": "US",
"language": "en",
"includeDescription": True,
})
items = client.dataset(run.default_dataset_id).list_items().items # apify-client 3.x returns a Run object
print(items)
5. In n8n
Paste this node into a workflow (it is a plain HTTP Request node). Create a Header Auth credential with name Authorization and value Bearer <APIFY_TOKEN>; each returned row becomes one item for the next node.
{
"nodes": [
{
"name": "Run arcadium/google-jobs",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
0,
0
],
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/arcadium~google-jobs/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"queries\":[\"software engineer\"],\"locations\":[\"Seattle, WA\"],\"datePosted\":\"any\",\"remoteOnly\":false,\"maxResultsPerQuery\":10,\"country\":\"US\",\"language\":\"en\",\"includeDescription\":true}",
"options": {
"timeout": 300000
}
}
}
],
"connections": {}
}
6. From an AI assistant (MCP)
Add Apify’s MCP server to Claude Desktop, Cursor, VS Code or any MCP client, limited to this actor:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/google-jobs",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}
More on the MCP page.
7. From LangChain
# pip install langchain-apify (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("arcadium/google-jobs")
rows = tool.invoke({"run_input": {
"queries": ["software engineer"],
"locations": ["Seattle, WA"],
"datePosted": "any",
"remoteOnly": False,
"maxResultsPerQuery": 10,
"country": "US",
"language": "en",
"includeDescription": True,
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])
Sample output
One row, from the example in the actor’s README. Long text is shortened and lists are cut to two items.
{
"rowType": "job",
"platform": "google-jobs",
"jobId": "d6Zuw_TVelot7iRuAAAAAA==",
"title": "Software Development Engineer, Network Monitoring and Remediation (NMR)",
"companyName": "Amazon Web Services, Inc.",
"location": "Seattle, WA",
"via": "Indeed",
"postedAgo": "5 days ago",
"postedAt": "2026-10-17",
"salaryText": "$144K–$194K a year",
"salary": {
"min": 144000,
"max": 194000,
"currency": "USD",
"period": "year",
"source": "structured"
},
"employmentType": "Full-time",
"employmentTypes": [
"FULLTIME"
],
"qualification": null,
"workFromHome": false,
"description": "DESCRIPTION\n\nAmazon's network carries traffic for hundreds of millions of customers ...",
"descriptionComplete": true,
"applyUrl": "https://www.indeed.com/viewjob?jk=917ad7a1f42a4176&utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
"applyOptions": [
{
"source": "Indeed",
"label": "Apply on Indeed",
"url": "https://www.indeed.com/viewjob?jk=917ad7a1f42a4176&utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
"domain": "indeed.com",
"ats": null
},
{
"source": "LinkedIn",
"label": "Apply on LinkedIn",
"url": "https://www.linkedin.com/jobs/view/software-development-engineer-network-monitoring-and-remediation-nmr-at-amazon-web-services-aws-4480587462?utm_campaign=go...",
"domain": "linkedin.com",
"ats": null
}
],
"googleJobsUrl": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer+jobs+in+seattle&htidocid=d6Zuw_TVelot7iRuAAAAAA%3D%3D",
"searchText": "software engineer in Seattle, WA",
"query": "software engineer",
"searchLocation": "Seattle, WA",
"position": 2,
"language": "en",
"country": "US",
"scrapedAt": "2026-10-22T08:00:00.000Z"
}
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. Values: 'job': one job posting from Google Jobs (charged). 'error': a search found nothing or could not be read; see code and message (free). |
platform | Always 'google-jobs'. |
jobId | Google's document id of the posting (htidocid), e.g. d6Zuw_TVelot7iRuAAAAAA==. The same posting keeps it across queries and runs: use it to deduplicate. |
title | Job title as published, e.g. Software Development Engineer II. |
companyName | Hiring organisation as Google lists it, e.g. Amazon Web Services, Inc. |
location | Job location as Google shows it, e.g. Seattle, WA or Berlin. Remote jobs may say Anywhere. |
via | Site Google read the posting from, e.g. LinkedIn, Indeed, Acme Careers (the 'via ...' line). |
postedAgo | Age as Google shows it, in the run language, e.g. 3 days ago, vor 2 Tagen. |
postedAt | Approximate posting date (yyyy-mm-dd) computed from postedAgo on the run day; '30+ days ago' gives a lower bound. Null when Google gave no age. |
salaryText | Salary as Google shows it, e.g. $144K–$194K a year, 30 € pro Stunde. Null when not stated. |
salary | Salary parsed from salaryText: min, max (equal for a single value), currency (ISO code), period (hour, day, week, month, year). |
employmentType | Employment type as Google shows it, e.g. Full-time, Contractor, Vollzeit. |
employmentTypes | Normalised employment types: FULLTIME, PARTTIME, CONTRACTOR, INTERN, TEMPORARY. Empty when unknown. |
qualification | Google's qualification chip, e.g. No degree mentioned. Null when not shown. |
workFromHome | True when Google marks the job as work from home. |
description | Job description text as Google shows it (includeDescription). Emails and phone numbers replaced with [email] and [phone]. |
descriptionComplete | True when description is the full text; false when Google showed only a preview (some markets show about 400 characters). |
applyUrl | Best apply link: the company's own applicant tracking system posting when Google lists one, else Google's first apply option. |
applyOptions | Every apply option Google lists: source (site name), label (button text), url, domain and ats (greenhouse, lever, workday, ... when the URL is a company job board). |
googleJobsUrl | google.com link that opens this posting in Google Jobs. |
searchText | Exact text sent to Google, with location and filters, e.g. software engineer in Seattle, WA part time. |
query | The search query from the input. |
searchLocation | The location from the input this row was found for; null without locations. |
position | Rank on Google's results page for searchText (1 = first). |
language | Google interface language used, e.g. en. |
country | Google market searched, e.g. US. |
jobsDb | jobsDbExport only: atsJobId (<ats>___<posting id>, as career-site-jobs names it), ats, boardToken, boardKey, atsUrl, applyUrls without tracking parameters, fingerprint (sha1 of company|title|location). |
scrapedAt | When the row was read (ISO 8601). |
input | Error rows: the search text that failed. |
code | Error rows: no_match (Google has no jobs for it), blocked, unavailable or invalid_input. |
message | Error rows: what happened, in plain words. |
Tutorials
Schedule it
In Apify Console, create a Task from your input and add a Schedule (for example daily). Each run writes a new dataset; integrations can push the rows to Google Sheets, Slack, a webhook or your database.