Arcadium Data Scrapers
Home / Guides / Google Jobs Scraper

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)

  1. Open arcadium/google-jobs and sign in to Apify (a free account works).
  2. Fill in the input form. The fields below are the ones the example uses.
  3. Set a maximum cost per run in the run options if you want a hard cap.
  4. Start the run. Rows appear in the Output tab as they arrive.
  5. Export the dataset as JSON, CSV or Excel, or connect an integration.
Input fieldTypeDescription
queriesarrayWhat 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.
locationsarrayPlaces 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.
datePostedstringOnly jobs posted within this window, the same filter as Google's own Date posted chip.
remoteOnlybooleanAdds Google's Remote filter (work from home jobs). The workFromHome field shows Google's own flag per job.
maxResultsPerQueryintegerJobs 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.
countrystringTwo-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).
languagestringGoogle 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.
includeDescriptionbooleanAdds 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"
}
FieldWhat it holds
rowTypeKind 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).
platformAlways 'google-jobs'.
jobIdGoogle's document id of the posting (htidocid), e.g. d6Zuw_TVelot7iRuAAAAAA==. The same posting keeps it across queries and runs: use it to deduplicate.
titleJob title as published, e.g. Software Development Engineer II.
companyNameHiring organisation as Google lists it, e.g. Amazon Web Services, Inc.
locationJob location as Google shows it, e.g. Seattle, WA or Berlin. Remote jobs may say Anywhere.
viaSite Google read the posting from, e.g. LinkedIn, Indeed, Acme Careers (the 'via ...' line).
postedAgoAge as Google shows it, in the run language, e.g. 3 days ago, vor 2 Tagen.
postedAtApproximate 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.
salaryTextSalary as Google shows it, e.g. $144K–$194K a year, 30 € pro Stunde. Null when not stated.
salarySalary parsed from salaryText: min, max (equal for a single value), currency (ISO code), period (hour, day, week, month, year).
employmentTypeEmployment type as Google shows it, e.g. Full-time, Contractor, Vollzeit.
employmentTypesNormalised employment types: FULLTIME, PARTTIME, CONTRACTOR, INTERN, TEMPORARY. Empty when unknown.
qualificationGoogle's qualification chip, e.g. No degree mentioned. Null when not shown.
workFromHomeTrue when Google marks the job as work from home.
descriptionJob description text as Google shows it (includeDescription). Emails and phone numbers replaced with [email] and [phone].
descriptionCompleteTrue when description is the full text; false when Google showed only a preview (some markets show about 400 characters).
applyUrlBest apply link: the company's own applicant tracking system posting when Google lists one, else Google's first apply option.
applyOptionsEvery 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).
googleJobsUrlgoogle.com link that opens this posting in Google Jobs.
searchTextExact text sent to Google, with location and filters, e.g. software engineer in Seattle, WA part time.
queryThe search query from the input.
searchLocationThe location from the input this row was found for; null without locations.
positionRank on Google's results page for searchText (1 = first).
languageGoogle interface language used, e.g. en.
countryGoogle market searched, e.g. US.
jobsDbjobsDbExport 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).
scrapedAtWhen the row was read (ISO 8601).
inputError rows: the search text that failed.
codeError rows: no_match (Google has no jobs for it), blocked, unavailable or invalid_input.
messageError 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.