# Google Jobs Scraper — Descriptions & Apply Links (`jeanswiegers/google-jobs-scraper`) Actor

Google Jobs employer grouping: export hiring companies, job counts, descriptions and apply links. Deduplicated search samples, not exhaustive pagination.

- **URL**: https://apify.com/jeanswiegers/google-jobs-scraper.md
- **Developed by:** [Jean Swiegers](https://apify.com/jeanswiegers) (community)
- **Categories:** Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 unique jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

### What does Google Jobs Scraper do?

**Google Jobs employer grouping**: find hiring companies by job keyword and turn public [Google Jobs search](https://www.google.com/search?q=software+engineer+jobs+near+London\&udm=8) results into structured records. This private prototype is an unofficial Google Jobs API alternative, not a Google product. It does not submit applications, collect recruiter contacts, access login-only content, or guarantee every listing on every job board.

### Why use Google Jobs search data?

Recruitment research, job-board feeds and labour-market monitoring all start with consistent role and employer data. Export job rows or group unique matching jobs by employer name for hiring signals. Employer-name grouping is not legal-entity verification. Apify offers API access, scheduling and integrations; scheduling should wait until coverage is validated.

### What data can it extract?

| Field | Type | Meaning |
|---|---|---|
| title | string | Public job title |
| company, location | string or null | Employer and displayed location |
| salaryText | string or null | Source salary text; no annualization |
| postedAtText | string or null | Displayed posting age or JSON-LD posting date |
| employmentType | string or null | Visible employment type |
| description | string or null | Description if present in the returned HTML |
| applyLinks | array | Public HTTPS destinations with source labels |
| jobId | string or null | Explicit source identifier when available |
| query, requestedLocation, collectedAt | strings | Search provenance and ISO collection time |

Company mode returns company, jobCount, jobTitles, locations, applyLinks (URL array) and collectedAt. Missing salary, description, employer or apply links are not guessed. Results may expose only snippets: this implementation does not call undocumented job-detail endpoints.

### How to scrape Google Jobs

1. Enter one role such as `software engineer` and a location such as `London, UK`.
2. Keep `maxResults` at 10 and `maxPages` at 1 for the first run.
3. Choose job rows or hiring-company groups.
4. Inspect `SUMMARY` for warnings before relying on coverage.
5. Download the dataset in JSON, HTML, CSV, or Excel.

### Input

See the input tab for full configuration options.

```json
{"queries":["software engineer"],"location":"London, UK","country":"gb","language":"en","maxResults":10,"maxPages":1,"outputMode":"jobs"}
```

`queries` accepts 1–10 searches. `maxResults` (1–1000) limits unique jobs **before** company grouping. `maxPages` (1–100) is the total request budget across all searches, not per query. More queries may remain unprocessed when that budget is reached. Only Apify's GOOGLE_SERP proxy is supported; no residential or browser fallback is attempted. Search country affects Google domain selection and the country parameter, but does not guarantee that Google interprets every location precisely. Interface parsing is English-first.

### Output example (illustrative fixture, not live data)

```json
[
  {"title":"Software Engineer (fixture)","company":"Example Ltd","location":"London","salaryText":null,"applyLinks":[{"source":"Example Jobs","url":"https://jobs.example.org/one"}]},
  {"title":"Data Engineer (fixture)","company":"Example Ltd","location":"Remote","salaryText":null,"applyLinks":[]}
]
```

Real rows include all fields listed above. `SUMMARY` reports requests, deduplication, output counts, per-page counts, resultLimitReached, coverage, stopReason and warnings. A SUCCEEDED run may have PARTIAL coverage; it does not guarantee that the requested result cap was reached. `SOURCE-HTML` holds the last private response for diagnostics. Data stays in the Actor run's default stores.

### How much does Google Jobs scraping cost?

No Store monetization or price is configured. Private testing consumes platform compute, storage and Google SERP proxy usage. Apify's public pricing page currently lists up to $2.50 per 1,000 SERP requests depending on plan, plus compute. One request is not one guaranteed job: yield and missing fields vary. Proposed future pricing is $2 per 1,000 unique jobs, subject to the owner's approval and measured costs. Company output uses the same underlying unique-job unit, not the number of grouped company rows. The `unique-job` hook respects the run charge cap; unpriced/private runs do not activate fees. No margin or coverage is promised.

### Limits, FAQ and support

#### Why did a search fail?

Consent, CAPTCHA, blocking and unrecognized HTML fail explicitly rather than silently returning an empty dataset. The Actor does not bypass consent, solve challenges, or retry with more expensive proxies. Google can change its markup at any time. A valid zero-result search requires an explicit empty-results marker.

#### Can it paginate?

Only ordinary public next-page links are followed, within the request budget. The tested Jobs responses had no such links. Standard Search start offsets were tested but did not paginate Jobs reliably, so they are not used as a fallback. JavaScript-only scrolling is not implemented: expect about ten jobs per individual search in the tested format. Opt-in `expandQueries: true` plans narrower senior/junior/lead/contract/graduate searches and deduplicates their first pages. Set `maxPages` to the total request budget (for example six) and `maxVariantsPerQuery` to the plan size. This is search fan-out, NOT true pagination or exhaustive collection; modifiers change the result mix. Each row retains both actual `query` and `originalQuery`. A result cap is a ceiling, not a promise. No undocumented async API is called. Jobs are deduplicated by explicit ID, otherwise normalized employer/title/location, with apply links merged.

#### Is this ready to launch?

This is a private technical beta with Store-ready draft documentation, not a validated commercial service. On 8 November 2026, cloud tests returned ten software-engineering jobs each for London, New York and Johannesburg with descriptions and apply destinations. A later opt-in London fan-out test returned **35 unique jobs, 35 descriptions and 35 apply-link sets from four searches**, removing three duplicates. This improves breadth beyond ten results per original query but is not true pagination: role modifiers change the result mix. Exhaustive single-query coverage, larger-scale reliability and customer validation remain unproven. Use the Issues tab for feedback and the API tab for integration once access is approved.

Respect Google's terms, robots directives, source attribution and applicable privacy laws. Job descriptions may incidentally contain personal information; use a lawful purpose, minimize retention and do not use this tool to harvest personal contacts. Apply links may expire and employer names may be ambiguous. This Actor is not affiliated with Google or any source job board.

### Expanded-search example (private validation)

```json
{"queries":["software engineer"],"location":"London, UK","country":"gb","maxResults":35,"maxPages":6,"expandQueries":true,"maxVariantsPerQuery":6}
```

One generated search consumes one SERP request even if it yields only duplicates. Expansion is off by default to protect small-run costs. It samples related roles rather than guaranteeing all matches. No pricing change is configured.

# Actor input Schema

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

One to ten job keywords or titles. No recruiter contact scraping.

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

City, region, or country. Included verbatim in the search query.

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

Two-letter search country, such as gb, us, or za.

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

Two-letter interface language. Selector coverage is currently English-first.

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

Total unique job cap, also before company grouping. Actual yield may be lower.

## `maxPages` (type: `integer`):

Total request budget across all queries, not per query. Start with one. Transient timeouts are retried automatically; no residential fallback.

## `outputMode` (type: `string`):

Jobs or employer-name groups. Company names are not verified legal entities.

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

Private prototype supports only the Google SERP group. No other proxies or fallback.

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

Opt-in first-page query fan-out, not true pagination. Searches senior/junior/lead/contract/graduate variants and deduplicates. The total request budget still applies.

## `maxVariantsPerQuery` (type: `integer`):

Maximum generated variants including the original, used only with expansion enabled. Six covers original, senior, junior, lead, contract, graduate.

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "location": "London, UK",
  "country": "gb",
  "language": "en",
  "maxResults": 10,
  "maxPages": 1,
  "outputMode": "jobs",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  },
  "expandQueries": false,
  "maxVariantsPerQuery": 6
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `summary` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jeanswiegers/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"] }

# Run the Actor and wait for it to finish
run = client.actor("jeanswiegers/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"
  ]
}' |
apify call jeanswiegers/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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