# Google Jobs Scraper - Salary, Highlights & Apply Links (`artificially/google-jobs-scraper`) Actor

Scrape Google Jobs (Google for Jobs) by search query and location. Output: one item per job with title, company, location, source board (via), posted date, employment type, salary, remote flag, full description, job highlights and every apply link. Filters: date posted, employment type, remote.

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

## Pricing

from $1.58 / 1,000 jobs

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, Highlights & Apply Links

Scrape **Google Jobs** (Google for Jobs, the "Jobs" tab in Google Search) by job title and location. One search covers LinkedIn, Indeed, Glassdoor, ZipRecruiter, Totaljobs, employer career sites and many other boards, already merged by Google. Every job comes back as clean JSON with title, company, location, the board it was found on (`via`), posted date, employment type, salary, remote flag, full description, Google's job highlights and every "Apply on …" link.

**Built by [Artificially](https://apify.com/artificially)** | Follow us on [X @artificially\_io](https://x.com/artificially_io)

#### Use with AI agents (MCP)

This actor works as a tool for Claude, ChatGPT, Cursor and other AI agents through [Apify's MCP server](https://mcp.apify.com). Ask something like "find remote data engineer jobs posted this week in London" and the agent calls it for you. Set `compactOutput: true` and a small `maxResultsPerQuery` (e.g. 10) so results fit easily in the agent's context.

**Quick setup** (sign in with your Apify account when asked):

- **Claude** (claude.ai or Claude Desktop): Settings → Connectors → Add custom connector, and paste `https://mcp.apify.com?tools=artificially/google-jobs-scraper`
- **Claude Code or Cursor** via the Apify CLI (latest version, `apify upgrade`): `apify mcp install claude-code --tools artificially/google-jobs-scraper` (use `cursor` instead of `claude-code` for Cursor)
- **Any MCP client** (Cursor, VS Code, Windsurf):

```json
{
  "mcpServers": {
    "apify": { "url": "https://mcp.apify.com?tools=artificially/google-jobs-scraper" }
  }
}
```

**Try asking:**

- "Find registered nurse jobs in Chicago posted this week on Google Jobs, with salary and apply links."
- "Search Google Jobs for remote data analyst roles in the US and summarize salary ranges."

### Why this actor

- **Every job board in one search** – Google Jobs aggregates postings from hundreds of boards and career sites; you get them deduplicated by Google's own job ID.
- **Real apply links** – every "Apply on LinkedIn / Indeed / company site" button with its destination URL, flagged when it is a direct application.
- **Structured fields** – salary parsed into `min`, `max`, `currency` and `period`; `postedAt` as an ISO date; normalized `employmentType`; `isRemote`; highlights split into qualifications, responsibilities and benefits.
- **Filters that map to Google** – date posted (24 hours, 3 days, week, month), employment type and remote only, plus country and language editions of Google (verified: US, UK, Canada, France).
- **More than 10 jobs per search** – Google shows about ten jobs per page. Ask for more and the actor follows further pages where available and runs related searches (by employment type, recency and seniority), keeping only new jobs.
- **Monitoring mode** – turn on `onlyNewSinceLastRun`, schedule the actor, and each run returns only jobs you have not seen yet.
- **Uses Apify's official Google SERP proxy** – no browser, no login, no cookies from you.
- **You only pay for results** – only valid jobs are saved and charged. Searches that return nothing are listed for free in `FAILED_SEARCHES`.

### Use cases

- **Job boards and aggregators** – fill a niche board with fresh listings from every major source, with working apply links.
- **Recruiters and sourcers** – see who is hiring for a role in a city, on which boards, and how fast.
- **Sales "hiring signal" leads** – companies hiring for specific roles are buying signals; feed new postings into your CRM daily.
- **Salary and labor-market research** – compare pay ranges, remote share and employment types across roles and countries.
- **Job seekers and communities** – alerts for "remote + senior + posted in the last 24 hours".

### Input

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `queries` | array | Job searches, e.g. `["software engineer", "registered nurse"]` ("jobs" is added automatically) | Required |
| `location` | string | City, region or country added as "in <location>" | – |
| `country` | string | Google edition / results country (`gl`): `us`, `uk`, `ca`, `fr`, … | `us` |
| `language` | string | Interface language (`hl`): `en`, `de`, `fr`, … | `en` |
| `datePosted` | string | `any`, `today`, `3days`, `week`, `month` | `any` |
| `employmentTypes` | array | `full-time`, `part-time`, `contractor`, `internship`, `temporary` | – |
| `remoteOnly` | boolean | Remote jobs only | `false` |
| `maxResultsPerQuery` | integer | Jobs to save per search (1–500) | `10` |
| `maxResults` | integer | Cap for the whole run | – |
| `expandQueries` | boolean | Run related searches to reach `maxResultsPerQuery` | `true` |
| `includeDescription` | boolean | Return the full description text | `true` |
| `onlyNewSinceLastRun` | boolean | Return only jobs not returned by earlier runs with the same input | `false` |
| `compactOutput` | boolean | Slim items with only the key fields. Best for AI agents | `false` |
| `maxConcurrency` | integer | Searches in parallel (1–10) | `3` |
| `proxyConfiguration` | object | Keep Apify proxy group `GOOGLE_SERP` | `GOOGLE_SERP` |

#### Example input

```json
{
    "queries": ["data engineer", "python developer"],
    "location": "London",
    "country": "uk",
    "datePosted": "week",
    "employmentTypes": ["full-time"],
    "maxResultsPerQuery": 30,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["GOOGLE_SERP"] }
}
```

### Output

```json
{
    "jobId": "1_Iqt1mT0QAAAAAA==",
    "title": "Registered Nurse (RN) - Evening Shift",
    "company": "Example Healthcare",
    "location": "Chicago, IL",
    "via": "LinkedIn",
    "postedAt": "2026-09-22T12:00:00.000Z",
    "postedAtRelative": "1 day ago",
    "employmentType": "full-time",
    "employmentTypeRaw": "Full-time",
    "salary": { "raw": "$39–$45 an hour", "min": 39, "max": 45, "currency": "USD", "period": "hour" },
    "isRemote": false,
    "tags": ["No degree mentioned", "Dental insurance"],
    "description": "Summary\n\nWe are hiring registered nurses for our evening shift...",
    "highlights": {
        "qualifications": ["Active RN license", "BLS certification"],
        "responsibilities": ["Provide direct patient care"],
        "benefits": ["Dental insurance", "Paid time off"],
        "sections": [{ "title": "Qualifications", "items": ["Active RN license", "BLS certification"] }]
    },
    "applyLinks": [
        { "title": "Apply on LinkedIn", "source": "LinkedIn", "url": "https://www.linkedin.com/jobs/view/...", "directApply": false },
        { "title": "Apply directly on Example Careers", "source": "Example Careers", "url": "https://careers.example.com/job/9", "directApply": true }
    ],
    "applyUrl": "https://www.linkedin.com/jobs/view/...",
    "shareUrl": "https://www.google.com/search?ibp=htl;jobs&q=registered+nurse&htidocid=...",
    "query": "registered nurse",
    "searchQuery": "registered nurse jobs in Chicago",
    "scrapedAt": "2026-09-23T12:00:00.000Z"
}
```

| Field | Description |
|-------|-------------|
| `jobId` | Google's job document ID; stable, use it to deduplicate across runs |
| `title`, `company`, `location` | As shown by Google |
| `via` | The board or site Google found the posting on |
| `postedAt`, `postedAtRelative` | ISO date computed from Google's "N days ago", and the original text |
| `employmentType` | `full-time`, `part-time`, `contractor`, `internship`, `temporary` or `null` (`employmentTypeRaw` keeps Google's text) |
| `salary` | `{ raw, min, max, currency, period }` or `null` when Google shows no pay; `currency` is `null` when Google shows no symbol |
| `isRemote` | `true` for work-from-home jobs or remote/anywhere locations |
| `tags` | Other Google chips such as benefits or "No degree mentioned" |
| `description` | Full description as plain text (when `includeDescription` is on) |
| `highlights` | Google's job highlights: `qualifications`, `responsibilities`, `benefits`, plus all `sections` as shown |
| `applyLinks`, `applyUrl` | Every apply option with its URL; `applyUrl` is the first one |
| `shareUrl` | Link to the job on Google Jobs |
| `query`, `searchQuery` | Your search and the exact Google search that found the job |

The key-value store also contains:

- `SUMMARY` – per-search counts, Google requests used, whether "more jobs" pagination was available, limits reached.
- `FAILED_SEARCHES` – searches that returned no jobs or were blocked, with a reason. These are never charged.

### Pricing

Pay-per-event: a tiny fee per run plus a fee per job saved. **You only pay for results** – duplicates, filtered-out jobs, empty searches and blocked pages are free, and Google SERP proxy costs are included. Set a maximum cost per run in Apify Console and the actor stops cleanly when it is reached. See the **Pricing** tab for current prices.

### FAQ

**How many jobs can I get per search?**
Google shows about ten jobs per results page. With `maxResultsPerQuery` above 10 the actor follows further result pages when Google provides them and runs related searches such as "… full time", "… senior" or "… in the last week" until the number is reached or no new jobs appear. Very narrow searches may simply have fewer jobs.

**How do I monitor a search for new jobs?**
Turn on `onlyNewSinceLastRun` and create an [Apify Schedule](https://docs.apify.com/platform/schedules), for example every morning with `datePosted: "today"`. The actor remembers the job IDs returned for that exact input and the next runs return only new postings. Changing the searches or filters starts a fresh history.

**Which countries and languages are supported?**
Set `country` (e.g. `us`, `uk`, `ca`, `fr`) and `language` (e.g. `en`, `fr`). Verified so far: US, UK, Canada and France. Google currently answers searches for Germany (`de`) with a captcha, so those return no jobs; you are not charged when a search returns nothing. Other countries usually work but are not yet verified. Dates, salary periods and employment types are parsed best in English; the raw texts are always kept.

**Why is salary missing for some jobs?**
Google shows pay only when the employer or board publishes it. We never guess.

**Why did a search return nothing?**
Check `FAILED_SEARCHES`. Either Google had no jobs for that search and filters (`no_results`), or the page could not be loaded. Make sure the proxy is set to the `GOOGLE_SERP` group. Failed searches are not charged.

**Is this legal?**
The actor reads public Google Search result pages through Apify's official Google SERP proxy. It does not log in or collect personal data about candidates. You are responsible for using the data in line with applicable laws and the sites' terms.

### Support

Found a search that does not work, or need another field? Open an issue on the actor's **Issues** tab – we usually respond within a day.

### Related actors

- [Career Site Jobs Scraper](https://apify.com/artificially/career-site-jobs-scraper): jobs straight from company career sites on Greenhouse, Lever, Ashby, Workday and more.
- [LinkedIn Jobs Scraper](https://apify.com/artificially/linkedin-jobs-scraper): job postings from LinkedIn search, across all companies.

# Actor input Schema

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

Required. One job search per entry, written the way you would type it into Google, usually a job title or skill. The word "jobs" is added automatically when missing. Example: \["software engineer", "registered nurse"]. Each search returns its own jobs, deduplicated across searches.

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

City, region or country added to every search as "in <location>". Example: "London", "Austin, TX", "Germany". Leave empty to let Google use the country below.

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

Two-letter country code of the Google edition to search (Google's gl parameter), which decides the country of the results. Verified: us, uk, ca, fr. Germany (de) is currently answered with a captcha by Google and returns nothing (not charged). Default: us.

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

Interface language code (Google's hl parameter). Examples: en, de, fr, es, pt. Default: en. Dates, salary periods and employment types are parsed best in English.

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

Only jobs posted within this window. Allowed values: any, today (last 24 hours), 3days, week, month. Default: any.

## `employmentTypes` (type: `array`):

Only these employment types. Allowed values: full-time, part-time, contractor, internship, temporary. Example: \["full-time", "contractor"]. Each selected type runs its own Google search. Leave empty for all types.

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

Set to true to search for remote jobs and keep only jobs Google marks as work from home or whose location/title says remote or anywhere.

## `maxResultsPerQuery` (type: `integer`):

Stop each search after saving this many jobs, from 1 to 500. Google shows about 10 jobs per results page; above 10 the actor opens more pages and related searches (by employment type, recency and seniority) until the number is reached or no new jobs appear. Example: 50. Default: 10.

## `maxResults` (type: `integer`):

Stop the whole run after saving this many jobs across all searches. Example: 100. Leave empty for no total limit (the run also stops at your maximum cost per run).

## `expandQueries` (type: `boolean`):

When true (default) and a search needs more jobs than Google's first page, the actor also runs related searches (e.g. "... full time", "... senior", "... in the last week") and keeps only new jobs. Set to false to run exactly the searches you entered.

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

Return the full job description as plain text in description. Set to false for smaller items.

## `onlyNewSinceLastRun` (type: `boolean`):

Set to true to remember the job IDs returned for this exact input (searches, location, country, language and filters) and return only jobs not seen in earlier runs. Ideal with Apify Schedules: you pay only for new postings.

## `compactOutput` (type: `boolean`):

Set to true to save a slim item per job with only jobId, title, company, location, via, isRemote, employmentType, salary (min, max, currency, period), postedAt, applyUrl and shareUrl. Description, highlights and the full apply-link list are dropped. Recommended when an AI agent or LLM reads the results. Leave false for the full item.

## `maxConcurrency` (type: `integer`):

How many searches run at the same time, from 1 to 10. Default: 3.

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

Keep the Apify GOOGLE\_SERP proxy group selected: it is Apify's official proxy for Google Search pages and is needed to get job results. Its cost is included in the per-job price.

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "location": "New York",
  "country": "us",
  "language": "en",
  "datePosted": "any",
  "remoteOnly": false,
  "maxResultsPerQuery": 10,
  "expandQueries": true,
  "includeDescription": true,
  "onlyNewSinceLastRun": false,
  "compactOutput": false,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

One item per job posting (overview table view)

## `summary` (type: `string`):

Per-query counts, Google requests used, pagination mode and limits reached

## `failedSearches` (type: `string`):

Searches that returned no jobs or were blocked, with a reason (never charged)

# 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",
    "maxResultsPerQuery": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("artificially/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",
    "maxResultsPerQuery": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

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

```

## MCP server setup

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