# Google Jobs Scraper — Listings, Salaries & Apply Links (`tortuga/google-jobs-scraper`) Actor

Returns Google Jobs listings for any search term, location and country: title, company, location, via (source site), salary with min/max/period, job type, posted date, full description, highlights, benefits and apply links resolved to publisher URLs.

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

## Pricing

from $5.50 / 1,000 job scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 — Listings, Salaries & Apply Links

Scrape the job listings that **Google Jobs** collects from LinkedIn, Indeed, ZipRecruiter, Glassdoor, company career sites and hundreds of other boards. Enter a search term, a location and a country, and get every job with its title, company, location, the site it came from ("via LinkedIn"), salary as shown and as numbers, job type, posted date, the **full job description**, Google's **job highlights** (qualifications, benefits, responsibilities) and **all apply links**, resolved to the publisher's own URL.

Filters work like on Google: date posted (past day, 3 days, week, month), job type (full-time, part-time, contractor, internship) and remote. Any Google country (google.com, google.co.uk, google.de, google.co.in, ...) and interface language.

Export to JSON, CSV or Excel, or pull the jobs through the API into Google Sheets, your ATS, a job board, a BI tool or an LLM pipeline. No Google account and no browser needed.

### What data does Google Jobs Scraper extract?

| Field | Description |
|---|---|
| `jobId` | Google Jobs id of the posting (stable across searches and runs) |
| `title` | Job title |
| `companyName`, `companyLogo` | Hiring company and its logo / thumbnail (when Google shows one) |
| `location` | Location as Google shows it, e.g. "New York, NY" |
| `via` | Where Google found the job, e.g. "LinkedIn", "Indeed", "Intuit Careers" |
| `postedAgo`, `postedAt` | Google's label ("6 days ago", "19 hours ago") and the approximate date it means (UTC, ISO 8601) |
| `scheduleType`, `jobTypes` | Job type as shown ("Full-time", "Full-time and Part-time") and as a list |
| `salaryText` | Salary as Google shows it, e.g. "$32–$67 an hour", "$130K–$180K a year" |
| `salaryMin`, `salaryMax`, `salaryPeriod`, `salaryCurrency` | Parsed salary: numbers, `hour` / `day` / `week` / `month` / `year`, ISO currency |
| `isRemote` | Work-from-home / remote job |
| `benefits` | Benefit badges: "Health insurance", "Dental insurance", "Paid time off" |
| `qualificationNote` | Degree badge, e.g. "No degree mentioned" |
| `extensions` | All badges exactly as shown on the job card |
| `description`, `descriptionIsPreview` | Full job description text (in EU countries Google shows only a preview; then the flag is `true`) |
| `highlights` | Google's job highlights: `[{"title": "Qualifications", "items": [...]}, {"title": "Benefits", ...}, {"title": "Responsibilities", ...}]` |
| `applyOptions` | Every "Apply on ..." button: `publisher`, `url` (publisher URL), `domain` |
| `applyUrl` | First apply link (usually the original posting) |
| `url` | Google Jobs share link that opens this job on Google |
| `position`, `searchQuery`, `searchLocation`, `searchVariant`, `country`, `language`, `scrapedAt` | Where the job appeared and which search found it |

### How to scrape Google Jobs

1. Enter one or more **Search terms** (e.g. `software engineer`, `registered nurse`, `barista`) and a **Location** (`New York, NY`, `London`, `Remote`...). You can also paste Google Jobs URLs (`https://www.google.com/search?q=...&udm=8`).
2. Pick the **Country** and **Language**, and optionally **Date posted**, **Job type** and **Remote only**.
3. Set **Max jobs** to cap the run and the cost.
4. Click **Start**. Jobs appear in the **Output** tab; download them or use the API.

### Input example

```json
{
  "queries": ["registered nurse", "nurse practitioner"],
  "location": "Chicago, IL",
  "country": "us",
  "language": "en",
  "datePosted": "week",
  "jobType": "any",
  "remoteOnly": false,
  "maxItems": 100,
  "maxPagesPerQuery": 10,
  "resolveApplyLinks": true
}
```

### Output example

```json
{
  "jobId": "y9TDXmLevxEZ_wZLAAAAAA==",
  "title": "UI Health - Staff Nurse I-5NW CDU",
  "companyName": "UI Health",
  "location": "Chicago, IL",
  "via": "LinkedIn",
  "postedAgo": "19 hours ago",
  "postedAt": "2026-10-11T01:00:00Z",
  "scheduleType": "Full-time",
  "jobTypes": ["Full-time"],
  "salaryText": "$32–$67 an hour",
  "salaryMin": 32,
  "salaryMax": 67,
  "salaryPeriod": "hour",
  "salaryCurrency": "USD",
  "isRemote": false,
  "benefits": ["Health insurance", "Paid time off", "Dental insurance"],
  "extensions": ["19 hours ago", "$32–$67 an hour", "Full-time", "Health insurance", "Paid time off", "Dental insurance"],
  "description": "Hiring Department: 5NW CDU-Hosp Observ Unit\n\nLocation: Chicago, IL USA\n\nRequisition ID: 1042519 ...",
  "descriptionIsPreview": false,
  "highlights": [
    {"title": "Qualifications", "items": ["Eligibility for licensure as a Registered Professional Nurse with the Illinois Department of Financial and Professional Regulation ...", "Graduated from a Registered Nurse program"]},
    {"title": "Benefits", "items": ["Work Schedule: 7am-7pm every other weekend", "..."]},
    {"title": "Responsibilities", "items": ["Shift: Flex Days", "..."]}
  ],
  "applyOptions": [
    {"publisher": "LinkedIn", "url": "https://www.linkedin.com/jobs/view/ui-health-staff-nurse-i-5nw-cdu-at-ui-health-4478089416?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic", "domain": "linkedin.com"},
    {"publisher": "Monster", "url": "https://www.monster.com/job-openings/ui-health-staff-nurse-i-orthopedics-chicago-il--fce83a99-...", "domain": "monster.com"}
  ],
  "applyUrl": "https://www.linkedin.com/jobs/view/ui-health-staff-nurse-i-5nw-cdu-at-ui-health-4478089416?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
  "companyLogo": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSOwsUnEWRCrN6l13IrkY76Cm3s45OZeVEd_8Bs&s=0",
  "url": "https://www.google.com/search?ibp=htl;jobs&q=registered+nurse+Chicago,+IL&htidocid=y9TDXmLevxEZ_wZLAAAAAA%3D%3D&hl=en-US",
  "position": 1,
  "searchQuery": "registered nurse",
  "searchLocation": "Chicago, IL",
  "searchVariant": "registered nurse Chicago, IL",
  "country": "us",
  "language": "en",
  "scrapedAt": "2026-10-11T20:33:04Z"
}
```

### How many jobs can I get per search?

Google shows 10 jobs per search page, and its "more jobs" scrolling only works inside a real browser session. To go further, the actor runs narrower sub-searches of your search: past day, past 3 days, past week, each job type, remote, and combinations. Each one returns its own top 10, and jobs found twice are saved once. **Max Google pages per search term** (default 10, up to 40) caps how many sub-searches run; the actor stops earlier when sub-searches stop finding new jobs or when Google has fewer than 10 jobs for the search. In our test, 6 pages gave 47 different jobs for "software engineer" in "New York, NY" (60 found, 13 duplicates). For more, add more search terms or locations (e.g. one per city or job title). Sub-searches need English (`en`); in other languages each search term gives up to 10 jobs.

### Monitor changes on a schedule

Turn on **Only new or changed items** and save the input as a task with a Schedule (Apify Console -> Schedules), for example every morning with **Date posted** = Past day. Each run remembers the jobs earlier runs of the same search returned and outputs only jobs it has not seen before; known jobs are not output and not charged (and their apply links are not resolved). New jobs get `changeType: "new"`. With monitoring on, **Max jobs** is the number of jobs checked per run. Use **Monitoring key** to keep several schedules on the same search apart.

### Does it work without a Google account or browser?

Yes. The actor reads the public Google Jobs results page over plain HTTP through Apify's GOOGLE_SERP proxy, which is built for Google Search pages. No login, cookies or browser are needed, which keeps runs fast and cheap.

### Pricing

Pay per event, no subscription:

- **$0.0055 per job** saved, with every field above (full description, highlights and resolved apply links included).

Apify also bills the GOOGLE_SERP proxy to your account as platform usage: about **$0.0025 per Google page of up to 10 jobs** (roughly $0.25-0.40 per 1,000 jobs), plus a little compute (about $0.05-0.10 per 1,000 jobs). 1,000 jobs cost about $5.50 + $0.30-0.50 usage. Monitoring runs only charge for new jobs.

### Proxy note

Since 2025 Google answers plain requests from datacenter and residential IPs with a JavaScript wall or an "unusual traffic" page. Apify's **GOOGLE_SERP** proxy group returns the real results page, so the actor always uses it (whatever is set in the Proxy field). A Google page takes 3-30 seconds through it, sometimes up to 2 minutes; the actor loads up to 4 pages at a time. Apply links are resolved by reading Google's redirect only (one light request per link, the publisher's page is never opened).

### Integrations and API

Use the results in Make, Zapier, n8n, Google Sheets or Airtable, or call the actor from Python / Node.js with the Apify client (see the **API** tab). A Schedule plus **Only new or changed items** gives you a daily feed of new jobs for a search term and city.

### Is it legal to scrape Google Jobs?

The actor reads only what Google shows publicly without login: job postings, company names, salary ranges and the links to the original postings. It does not log in and collects no job seeker data. Job descriptions belong to the employers and job boards that published them; you are responsible for how you use the data and for complying with Google's terms and applicable law (for example the GDPR or CCPA).

### Support

Found a bug or need a field? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

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

One Google Jobs search per term, as you would type it on Google, e.g. "software engineer", "registered nurse", "barista". You can put the place in the term ("nurse jobs in Chicago") or use Location below.

## `location` (type: `string`):

City, region or country added to every search term, e.g. "New York, NY", "London", "Berlin", "Remote". Leave empty to let Google pick by country.

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

Google country: which Google domain is searched (google.com, google.co.uk, google.de, ...) and which market the jobs come from.

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

Google interface language code, e.g. en, de, fr, es, pt, it, nl. Labels such as "6 days ago" or "Full-time" come in this language. Getting more than 10 jobs per search (sub-searches) needs English (en).

## `datePosted` (type: `string`):

Only jobs posted in this period (Google Jobs' Date posted filter).

## `jobType` (type: `string`):

Only jobs of this type (Google Jobs' Job type filter).

## `remoteOnly` (type: `boolean`):

Only remote jobs (Google Jobs' Remote filter).

## `maxItems` (type: `integer`):

Stop after this many jobs in total (you pay per job saved).

## `maxPagesPerQuery` (type: `integer`):

Google shows 10 jobs per search. To get more, the actor runs narrower sub-searches (past day/3 days/week, full-time, part-time, contractor, internship, remote, and combinations) and removes duplicates. Each page is one Google SERP proxy request (about $0.0025, billed by Apify as proxy usage). It stops early when sub-searches stop finding new jobs.

## `resolveApplyLinks` (type: `boolean`):

Turn Google's apply buttons (google.com/goto redirects) into the publisher's own URL (LinkedIn, Indeed, the company career site, ...). Reads the redirect only; the publisher's page is not opened.

## `startUrls` (type: `array`):

Optional: Google Jobs search URLs, e.g. https://www.google.com/search?q=data+analyst+london\&udm=8. The q, gl and hl parameters are used; the filters above apply too.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. For Google Jobs: only jobs that earlier runs did not output; Max jobs is then the number of jobs checked per run.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input

## `proxyConfiguration` (type: `object`):

Google Jobs loads only through Apify's GOOGLE_SERP proxy group (Google blocks plain datacenter and residential requests with a JavaScript wall). The actor always uses it. Apify bills it as proxy usage, about $0.0025 per Google page (10 jobs).

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "location": "New York, NY",
  "country": "us",
  "language": "en",
  "datePosted": "any",
  "jobType": "any",
  "remoteOnly": false,
  "maxItems": 100,
  "maxPagesPerQuery": 10,
  "resolveApplyLinks": true,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

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

No description

# 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": [
        "software engineer"
    ],
    "location": "New York, NY",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/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": ["software engineer"],
    "location": "New York, NY",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/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": [
    "software engineer"
  ],
  "location": "New York, NY",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}' |
apify call tortuga/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tortuga/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/MhNhxA2hC8rxMdVr0/builds/OCGnBEDWrys3CQr8v/openapi.json
