# Google Jobs Scraper - fast, cheap, salary parsed (`eszetael_lab/google-jobs-scraper`) Actor

Fast and affordable Google Jobs scraper & job listings scraper API. Extracts Google Jobs with parsed salary (min/max/currency/period), direct apply links, job highlights, and incremental monitoring (onlyNew). Transparent status messages — never pay for empty runs.

- **URL**: https://apify.com/eszetael_lab/google-jobs-scraper.md
- **Developed by:** [Radosław Szal](https://apify.com/eszetael_lab) (community)
- **Categories:** Jobs, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 result items

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

## Google Jobs Scraper - Fast, Cheap, Salary Parsed

The **Google Jobs Scraper** is a high-performance, cost-effective **google jobs api** and **job listings scraper** that extracts comprehensive, structured job postings from Google Jobs with parsed salaries, direct application links, and incremental monitoring.

***

### What it does

Google Jobs Scraper retrieves public job listings from Google Jobs (`/search?udm=8`) through Apify's dedicated Google SERP proxy. It converts dynamic search results into clean, flat JSON records ready for your database, analytics pipeline, or CRM.

- **Deep Salary Breakdown**: Parses raw salary strings into structured numeric values: `salaryMin`, `salaryMax`, ISO 4217 `salaryCurrency` (e.g. `USD`, `EUR`, `GBP`, `PLN`), and payment period (`salaryPeriod`: `YEAR`, `MONTH`, `WEEK`, `DAY`, `HOUR`), while retaining the original `salaryText`.
- **All Application Links**: Captures every application redirect link (`applyLinks`) with its platform label (e.g., LinkedIn, Indeed, Company Site) and source name (`via`).
- **Complete Job Details**: Extracts job title, hiring company, location, employment type (Full-time, Part-time, Contract, etc.), posting date (`postedAt` in ISO-8601 UTC and original `postedText`), and metadata tags.
- **Sanitized Descriptions & Highlights**: Delivers clean, HTML-stripped job descriptions with emails automatically redacted for privacy, alongside parsed structured `highlights` (Qualifications, Responsibilities, Benefits).
- **Search Matrix Scaling**: Supports multi-query and multi-location searches in a single run (up to 50 queries × 50 locations, capped at 100 combinations).
- **Incremental Monitoring (`onlyNew`)**: Remembers previously scraped listings in a persistent Key-Value store (`SEEN`) to only output new openings during scheduled recurring runs.
- **Global Coverage**: Fully customizable Google country code (`countryCode` / `gl`) and interface language (`languageCode` / `hl`).

***

### Why choose this actor

Here is how this scraper compares to typical market alternatives:

1. **High Reliability (≥98%)**: Built exclusively on lightweight HTTP requests routed via Apify's official `GOOGLE_SERP` proxy with automated session rotation. Unlike browser-heavy scrapers that frequently suffer 8% to 89% failure and block rates, this actor delivers consistent, high-uptime extraction.
2. **Fair & Transparent Execution (Zero Empty Charges)**: We never report false success with an empty dataset. If no jobs match your criteria, the run finishes with a transparent `statusMessage` detailing the cause (`NO_RESULTS`, filter mismatch, or SERP block). You are never charged for empty runs.
3. **Structured Salary Parsing**: Instead of returning unparsed, ambiguous text blocks, salaries are separated into numeric minimums, maximums, currency, and period. You can immediately filter and query salary brackets without post-processing.
4. **All Application Links with Cross-Query Deduplication**: Gathers all application routes instead of just the first link. Automatic deduplication by Google document ID (`jobId`) ensures you never receive duplicate records across overlapping search queries or locations.
5. **Native Incremental Runs (`onlyNew`)**: Set up recurring hourly or daily schedules without paying for duplicate listings. Only newly discovered positions are pushed and charged.

***

### Input

Configure your search using the following parameters:

```json
{
  "queries": [
    "software engineer",
    "backend developer"
  ],
  "locations": [
    "New York, NY",
    "Remote"
  ],
  "countryCode": "us",
  "languageCode": "en",
  "maxItemsPerQuery": 20,
  "maxItems": 100,
  "datePosted": "week",
  "onlyNew": false
}
```

#### Input Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | `string[]` | *Required* | List of job titles, roles, or keywords (e.g. `["software engineer"]`). Up to 50 queries. |
| `locations` | `string[]` | `["New York"]` | Locations or remote filters (e.g. `["New York", "Remote"]`). Max 100 query × location combinations. |
| `countryCode` | `string` | `"us"` | Two-letter Google country code (`gl` parameter), e.g. `us`, `de`, `gb`, `pl`. |
| `languageCode` | `string` | `"en"` | Two-letter Google language code (`hl` parameter), e.g. `en`, `de`, `pl`. |
| `maxItemsPerQuery` | `integer` | `20` | Max items per query combination. Each Google page contains ~10 listings (pagination is scaled via query/location combinations). |
| `maxItems` | `integer` | `100` | Hard cap on total results across the entire run to prevent budget overruns. |
| `datePosted` | `string` | `"any"` | Date filter: `any`, `today` (past 24h), `3days`, `week`, or `month`. |
| `onlyNew` | `boolean` | `false` | When enabled, skips jobs already processed in previous runs via the `SEEN` Key-Value store. |

***

### Output

Each job offer is stored as a flat, comprehensive JSON record in the default dataset:

```json
{
  "jobId": "fp8W9b3Qk2A10z_rAAAAAA==",
  "title": "Senior Software Engineer - Backend",
  "company": "Acme Technologies",
  "location": "New York, NY",
  "via": "LinkedIn",
  "postedAt": "2026-10-22T00:00:00+00:00",
  "postedText": "4 days ago",
  "employmentType": "Full-time",
  "salaryMin": 140000,
  "salaryMax": 185000,
  "salaryCurrency": "USD",
  "salaryPeriod": "YEAR",
  "salaryText": "$140,000 - $185,000 a year",
  "description": "We are seeking an experienced Backend Engineer to lead our core services team. In this role, you will design scalable APIs, optimize distributed data pipelines, and collaborate with product teams. Contact us at [email removed] for any questions.",
  "descriptionLength": 251,
  "highlights": {
    "Qualifications": [
      "5+ years of production experience in Python, Go, or Java",
      "Hands-on expertise with PostgreSQL and distributed message brokers"
    ],
    "Responsibilities": [
      "Architect and scale core microservices",
      "Lead technical design reviews and mentor team members"
    ],
    "Benefits": [
      "Competitive health, dental, and vision coverage",
      "401(k) matching up to 5%",
      "Flexible hybrid and remote work options"
    ]
  },
  "applyLinks": [
    {
      "label": "Apply on LinkedIn",
      "url": "https://www.google.com/url?q=https%3A%2F%2Fwww.linkedin.com%2Fjobs%2Fview%2F123456789"
    },
    {
      "label": "Apply on Company Site",
      "url": "https://www.google.com/url?q=https%3A%2F%2Fcareers.acme.example.com%2Fjob%2Fsenior-backend"
    }
  ],
  "tags": [
    "Full-time",
    "Health insurance",
    "Paid time off"
  ],
  "query": "software engineer",
  "location_query": "New York, NY",
  "countryCode": "us",
  "languageCode": "en",
  "scrapedAt": "2026-10-26T12:00:00.000Z"
}
```

***

### Pricing

This actor uses a transparent **Pay-Per-Event (PPE)** pricing model:

- **$0.002 per job record** (`result-item`).
- Scraping **1,000 job listings costs just $2.00**.

#### Market Comparison

| Pricing Model | Typical Market Rate | This Actor |
|---|---|---|
| Per job result | $0.01 – $0.03 | **$0.002** (5x to 15x cheaper) |
| Per page fee | $0.09 – $0.20 / page | **$0.00** (no per-page charges) |
| Empty / failed runs | Often billed | **$0.00** (never charged on 0 results) |
| Startup / monthly minimum | Often required | **$0.00** (pay only for what you extract) |

You only pay for valid, successfully extracted job records pushed to your dataset.

***

### FAQ

#### 1. How many job listings can I extract per search?

A single Google Jobs SERP page provides approximately 10 listings per query. Because Google Jobs does not support pagination on this interface, scale your extraction by utilizing the search matrix: provide multiple related titles in `queries` (e.g. `["backend engineer", "python developer", "software engineer"]`) and multiple locations in `locations`. The actor automatically runs the product of queries × locations (up to 100 combinations).

#### 2. How does the incremental monitoring (`onlyNew`) feature work?

When `onlyNew: true` is configured, the actor checks each extracted job against a list of previously scraped IDs stored in the `SEEN` Key-Value store. Any job that was delivered in an earlier run is skipped automatically and not charged. This makes it ideal for automated, scheduled runs (e.g. daily alerts).

#### 3. Can I filter jobs by publication date?

Yes. You can set `datePosted` to `today` (past 24 hours), `3days`, `week`, or `month`. Note that Google's search parameter for date filtering is optimized for English queries (`languageCode: "en"`); for other languages, it is ignored safely to prevent unintended zero-result drops.

#### 4. Does this actor extract personal contact info for recruiters?

No. In compliance with strict privacy and GDPR standards, this actor exclusively extracts organizational and employer job postings. Personal recruiter profiles and direct contacts are outside its scope. Furthermore, any email addresses found inside job descriptions are automatically redacted and replaced with `[email removed]`.

#### 5. What happens if Google blocks a request or returns zero results?

The actor implements a fail-on-zero policy. If 0 offers are found, it does not record a misleading success; instead, it sets a clear diagnostic status message (distinguishing between natural `NO_RESULTS`, query mismatch, or SERP blocks) and terminates without charging your account. In addition, when unexpected page layout changes occur, the first 200 KB of HTML is preserved in the Key-Value store under `DEBUG_*` for inspection.

***

### Legality & Compliance

- **Public Data Only**: The actor collects publicly available Google search engine results without bypassing authentication, paywalls, or login requirements.
- **Privacy Protection**: Extracts corporate hiring information only. Recruiter personal data is not collected, and email addresses in descriptions are automatically redacted.
- **User-Directed Queries**: Searches are executed strictly on user demand with configurable quantity caps; there is no autonomous mass crawling.
- **Redirects Only**: Application URLs are captured as Google redirect links; external job board pages are not crawled or scraped.
- **User Responsibility**: Users are responsible for ensuring that their downstream storage, processing, and use of collected data adhere to applicable local laws, regulations, and third-party terms.

***

### Feedback & Reviews

We actively maintain and improve the Google Jobs Scraper. If this actor saved you time, reduced your infrastructure expenses, or simplified your data pipeline, **please consider leaving a 5-star review on the Apify Store**. Your feedback and suggestions directly guide future updates!

# Actor input Schema

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

Job titles or keywords to search for (e.g. 'software engineer', 'product manager'). Up to 50 queries.

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

Locations to search in (e.g. 'New York', 'Berlin', 'London', 'Remote'). Total query combinations (queries × locations) is capped at 100.

## `countryCode` (type: `string`):

Two-letter Google country code (gl parameter), e.g. 'us', 'de', 'gb', 'pl'.

## `languageCode` (type: `string`):

Two-letter Google interface language code (hl parameter), e.g. 'en', 'de', 'pl'.

## `maxItemsPerQuery` (type: `integer`):

Maximum offers to collect per query combination. Note: A single Google Jobs page returns ~10 offers per query (pagination via 'start=' is not supported by Google SERP). To get more results, combine multiple queries or locations.

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

Hard total cap for the entire run to prevent budget overruns.

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

Filter jobs by posting date. Note: Google search filter applies to English queries only ('en'); for other languages it is safely ignored.

## `onlyNew` (type: `boolean`):

Skip job listings already seen in previous runs (tracked in the SEEN key-value store). Useful for recurring scheduled monitoring.

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "locations": [
    "New York"
  ],
  "countryCode": "us",
  "languageCode": "en",
  "maxItemsPerQuery": 20,
  "maxItems": 20,
  "datePosted": "any",
  "onlyNew": false
}
```

# Actor output Schema

## `allJobs` (type: `string`):

All job offers collected during this run with parsed salary, company, location, application links, and highlights.

# 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"
    ],
    "locations": [
        "New York"
    ],
    "countryCode": "us",
    "languageCode": "en",
    "maxItemsPerQuery": 20,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("eszetael_lab/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"],
    "locations": ["New York"],
    "countryCode": "us",
    "languageCode": "en",
    "maxItemsPerQuery": 20,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("eszetael_lab/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"
  ],
  "locations": [
    "New York"
  ],
  "countryCode": "us",
  "languageCode": "en",
  "maxItemsPerQuery": 20,
  "maxItems": 20
}' |
apify call eszetael_lab/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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