# Google Jobs Scraper - Salary, Apply Links, Descriptions (`om_kh/google-jobs-scraper`) Actor

Scrape Google Jobs for any keyword and city: title, company, location, salary (min/max), posted date, job type, skills, years of experience, full description and every apply link (LinkedIn, Indeed, Glassdoor, career sites). $2.50 per 1,000 jobs on paid plans (from $2), no start fee.

- **URL**: https://apify.com/om_kh/google-jobs-scraper.md
- **Developed by:** [Khandji Omar](https://apify.com/om_kh) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job postings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Jobs Scraper — Salary, Apply Links, Descriptions

> Scrape **Google Jobs** — the index that merges **LinkedIn, Indeed, Glassdoor, ZipRecruiter** and
> company career sites — for any keyword and location: job title, **company**, location, source,
> **posted date**, job type, **salary parsed into min / max / period**, qualifications, benefits,
> **full description** and **every "Apply on" link**. Built for reliability: every Google page is
> retried on a fresh session, and one failed page never fails the run.
> **$2.50 per 1,000 jobs on paid Apify plans (down to $2), no start fee.**

### What does this Google Jobs scraper do?

Type job searches ("registered nurse", "python developer", "warehouse") and locations ("Houston",
"Texas", "London"). The scraper reads Google Jobs and returns one clean row per job posting, with
duplicates removed. Google shows 10 jobs per page, so each search runs several filter variants
in parallel (full time, part time, remote, contract, posted today…) to collect up to 140 different
jobs per search.

### Why use it

1. **One source for every job board:** LinkedIn, Indeed, Glassdoor, ZipRecruiter, Built In and
   company career pages in a single feed — with each board's direct apply link.
2. **Salary as numbers:** `salaryMin`, `salaryMax`, `salaryPeriod` (hour / year…) ready for analysis.
3. **Full content:** description, qualifications, responsibilities and benefits.
4. **Reliable:** retries with fresh sessions, per-search error reports, partial pages never lost.
5. **Filters:** posted within (today, 3 days, week, month), job type, only jobs with a salary.
6. **Cheaper than the alternatives:** from $0.002 to $0.0025 per job on paid plans, no start fee.

### How to use it in 3 steps

1. Click **Try for free** — "data analyst" in Chicago is prefilled.
2. Enter your job searches and locations.
3. Click **Start** and download JSON, CSV or Excel.

### Input

| Field | What it does |
|---|---|
| `queries` | Job titles or keywords. |
| `locations` | Cities, states or countries; each search runs in each location. |
| `radiusKm` | Asks Google to search within this distance of each location (1 to 300 km). Google treats it as a hint, not a strict border. |
| `strictLocation` | Keeps only jobs whose location matches the city or the state/region you typed (`Austin, TX` keeps all of Texas). Remote jobs are kept. Default off. |
| `maxJobsPerSearch` | 1 to 140. Default 50. |
| `postedWithin` | Any time, today, last 3 days, this week, this month. |
| `scheduleType` | Full-time, part-time, contractor, internship, temporary. |
| `onlyWithSalary` | Keep only postings that show a salary. |
| `includeDescription` | Turn off for lighter rows. |
| `country` / `language` | Google Jobs market (`us`, `gb`, `ca`, `au`, `in`…) and language. |
| `googleDomain` | Google site to search: `google.com` (default), `google.co.uk`, `google.ca`, `google.de`, `google.fr`, `google.com.au`… |
| `maxTotalChargeUsd` | Optional hard cost cap for the run. |

```json
{
  "queries": ["registered nurse", "physical therapist"],
  "locations": ["Houston", "Dallas"],
  "maxJobsPerSearch": 100,
  "postedWithin": "week",
  "onlyWithSalary": true
}
```

### Output

Real example (Chicago, lists and description shortened):

```json
{
  "jobId": "llN7Zv11AL5HcVBoAAAAAA==",
  "title": "Data Analyst II",
  "companyName": "Shirley Ryan AbilityLab",
  "location": "Chicago, IL",
  "via": "Built In Chicago",
  "postedAgo": "17 days ago",
  "postedAt": "2026-09-14",
  "scheduleType": "Full-time",
  "salary": "71.2K–124K a year",
  "salaryMin": 71200.0,
  "salaryMax": 124000.0,
  "salaryPeriod": "year",
  "isRemote": false,
  "benefits": ["Health insurance"],
  "qualifications": ["…"],
  "responsibilities": ["…"],
  "description": "…",
  "applyUrl": "https://builtin.com/job/…",
  "applyLinks": [
    {"source": "builtin.com", "url": "https://builtin.com/job/…"},
    {"source": "linkedin.com", "url": "https://www.linkedin.com/jobs/view/…"}
  ],
  "extensions": ["4 days ago", "Full-time"],
  "experienceYears": 1,
  "skills": ["Workday"],
  "visaSponsorship": null,
  "education": null,
  "googleUrl": "https://www.google.com/search?q=Registered+Nurse+%28Rn%29%2C+Primary+Care+The+University+of+Texas+at+Austin+Dell+Medical+Center&udm=8&hl=en&gl=us",
  "rank": 4,
  "searchQuery": "registered nurse",
  "searchLocation": "Austin, TX",
  "country": "us",
  "language": "en"
}
```

On top of what Google shows, every row carries facts read from the description by plain rules (no AI, no extra cost):
`experienceYears` (the lowest number of years asked), `skills` (from a list of about 90 tools), `visaSponsorship`
(`yes` / `no` when the text says so) and `education`. They stay empty when the text does not say.
`extensions` is the raw list of tags under the job, `googleUrl` reopens the job on Google, and `rank`, `searchQuery`,
`searchLocation`, `country` and `language` say which search found it. (These last eleven values come from another real posting: "Registered Nurse (Rn), Primary Care" at The University of Texas at Austin Dell Medical Center.)

### How much does it cost?

| Event | Price |
|---|---|
| Job posting, paid Apify plans | **$0.0025** ($2.50 per 1,000), down to $0.002 on the largest plans |
| Job posting, free Apify plan | $0.003 |
| Start fee | none |

Up to 20 jobs of every run are free (at most half of the run). Searches Google cannot answer are
reported in the run summary and never charged. Paid Apify plans get lower tier prices.

### Use cases

- **Job boards and aggregators** — fresh postings from every source, deduplicated.
- **Recruiters and staffing agencies** — who is hiring for which role, where, at what pay.
- **Sales teams** — companies hiring = companies growing and buying.
- **Salary research** — pay ranges by title and city.
- **Career sites and newsletters** — daily feeds of new jobs in a niche.

### Use it from code (API)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("om_kh/google-jobs-scraper").call(run_input={
    "queries": ["machine learning engineer"],
    "locations": ["New York"],
    "postedWithin": "3days",
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["companyName"], job.get("salary"), job["applyUrl"])
```

```bash
curl -X POST "https://api.apify.com/v2/acts/om_kh~google-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["nurse"], "locations": ["Houston"], "maxJobsPerSearch": 20}'
```

### Integrations and MCP

Schedule it daily with `postedWithin: "today"` and send new jobs to Google Sheets, Slack, Airtable
or your ATS with n8n, Make or Zapier. AI agents can call it through `https://mcp.apify.com` as
`om_kh/google-jobs-scraper`.

### Tips and limits

- Google Jobs holds a few hundred postings per search at most: for full coverage, split by city
  or by more specific titles.
- **Always give a location.** With a country alone, Google mostly returns United States jobs.
  For another country, set the location, the `country` and the matching `googleDomain`.
- **Countries.** Checked on 6 October 2026 with one large city per country and the local Google
  domain. Local jobs came back in 31 countries: United States, United Kingdom, Canada, India,
  Germany, France, Spain, Italy, Netherlands, Switzerland, Belgium, Austria, Denmark, Brazil,
  Mexico, Argentina, Colombia, Chile, Japan, Singapore, Philippines, Indonesia, Malaysia,
  Thailand, Pakistan, United Arab Emirates, Saudi Arabia, Egypt, South Africa, Nigeria, Kenya.
  In Belgium, Austria, Denmark and Thailand the search must be written in the local language
  ("emploi", "stellenangebote", "job", "งาน") with the matching `language`. No job came back in
  9, in English or in the local language: Australia, New Zealand, Ireland, Sweden, Norway,
  Finland, Poland, Portugal, South Korea. Other countries were not checked.
- When Google answers with no job at all, the run says so in plain words ("Google Jobs may not
  exist in this country") and charges nothing.
- Google sometimes mixes in jobs from other places; `strictLocation` removes them.
- `postedAt` is computed from Google's "3 days ago" label (day precision).
- Salary is only present when the employer or the board publishes it.

### FAQ

**Do I need a Google account or an API key?** No.

**Does it include LinkedIn and Indeed jobs?** Yes, when Google Jobs lists them — with the direct
LinkedIn / Indeed apply links.

**Is it legal?** It reads public search results. Use the data in line with the laws and terms that
apply to you.

### Related Actors

- [ATS Jobs API](https://apify.com/om_kh/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workday boards.
- [Careers Page Scraper](https://apify.com/om_kh/careers-page-scraper) — all jobs of a list of company websites.
- [Hiring Signals API](https://apify.com/om_kh/company-hiring-signals) — which companies are hiring for which roles.

# Actor input Schema

## `queries` (type: `array`):

Job titles or keywords: 'data analyst', 'registered nurse', 'python developer remote' (up to 50 with locations).

## `locations` (type: `array`):

Cities, states or countries: 'Chicago', 'Texas', 'London'. Each search runs in each location.

## `radiusKm` (type: `integer`):

Asks Google to search within this distance of each location, 1 to 300 km. Google treats it as a hint, not a strict border. Leave empty for Google's own default area.

## `strictLocation` (type: `boolean`):

Google sometimes adds jobs from other places. Turn on to keep only jobs whose location matches the city or the state/region you typed (Austin, TX keeps all of Texas). Remote jobs are kept.

## `maxJobsPerSearch` (type: `integer`):

1 to 140. Google shows 10 jobs per page; the scraper runs filter variants in parallel to go further.

## `postedWithin` (type: `string`):

Only recent postings.

## `scheduleType` (type: `string`):

Keep only this job type.

## `onlyWithSalary` (type: `boolean`):

Keep only postings that show a salary.

## `includeDescription` (type: `boolean`):

Turn off for lighter rows.

## `country` (type: `string`):

Two-letter country code of the Google Jobs market: us, gb, ca, au, in, de, fr...

## `language` (type: `string`):

Interface language, e.g. en.

## `googleDomain` (type: `string`):

Which Google site to search: google.com, google.co.uk, google.ca, google.de, google.fr, google.com.au... Use it with the matching country.

## `maxTotalChargeUsd` (type: `number`):

Optional hard cost cap for this run.

## Actor input object example

```json
{
  "queries": [
    "data analyst"
  ],
  "locations": [
    "Chicago"
  ],
  "strictLocation": false,
  "maxJobsPerSearch": 20,
  "postedWithin": "any",
  "scheduleType": "any",
  "onlyWithSalary": false,
  "includeDescription": true,
  "country": "us",
  "language": "en",
  "googleDomain": "google.com"
}
```

# Actor output Schema

## `report` (type: `string`):

A visual summary of delivery, charges, and source issues.

## `results` (type: `string`):

Jobs in a sortable table. No JSON knowledge required.

## `csv` (type: `string`):

Results ready for spreadsheets, CRMs, and analytics tools.

## `excel` (type: `string`):

Results as an Excel workbook for non-technical teams.

## `runSummary` (type: `string`):

Machine-readable delivery, billing, and source diagnostics.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "data analyst"
    ],
    "locations": [
        "Chicago"
    ],
    "maxJobsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("om_kh/google-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": ["data analyst"],
    "locations": ["Chicago"],
    "maxJobsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("om_kh/google-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "data analyst"
  ],
  "locations": [
    "Chicago"
  ],
  "maxJobsPerSearch": 20
}' |
apify call om_kh/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,om_kh/google-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Ox3oAVMsMelHga6hL/builds/my0UH3fBj3pPUsqDU/openapi.json
