# Google Jobs Scraper - Reliable (`atlasdata/google-jobs-scraper-reliable`) Actor

Scrape Google Jobs (Google for Jobs) listings: title, company, location, source, posted date, salary, job type, full description, highlights and direct apply links. Filters for date posted, job type, remote, any country and language. Pay only per job.

- **URL**: https://apify.com/atlasdata/google-jobs-scraper-reliable.md
- **Developed by:** [Christian Machon](https://apify.com/atlasdata) (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 $3.00 / 1,000 job scrapeds

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 & API - Reliable

Scrape **Google Jobs** (the "Google for Jobs" panel in Google Search) by **keyword, location, country and language**, with Google's own filters for **date posted, job type (full-time, part-time, contract, internship) and remote**. Each job comes with title, company, location, the job board it was found on, posted date, **salary (parsed into min / max / currency / period)**, job type, qualifications, benefits, the **description, highlights and every "Apply on ..." link with the direct URL** to the employer or job board.

It uses Apify's Google SERP proxy (included in the price), so there are no CAPTCHAs and no blocked runs. When Google returns a page without the jobs panel, the Actor retries it automatically on a new connection.

### What can you use it for?

- **Job market research**: who is hiring for a role in a city, how many postings there are, which job boards carry them, and how fresh they are.
- **Salary benchmarks**: Google shows a salary on many postings. You get it as text and as numbers (min, max, currency, hour/year).
- **Lead generation for recruiters and staffing agencies**: companies that are hiring right now, with links to their postings.
- **Job boards and aggregators**: feed fresh postings, with direct apply URLs, into your own site or alerts.
- **Monitoring**: schedule a daily run with *Date posted = Since yesterday* to get only new jobs.

### How to use it

1. Enter one or more **search queries** (a job title or keywords, e.g. `nurse`, `data analyst`, `barista part time`). Each query is a separate search.
2. Add a **location** (city, region or country) and set the **country** (`us`, `gb`, `de`, `in` ...) and **language** (`en`, `de`, `fr`, `es` ...).
3. Optionally pick **date posted**, **job type** and **remote only**.
4. Set **max jobs per query**.
5. Run. Jobs go to the dataset, and a per-query summary goes to the `OUTPUT` record in the key-value store.

You can also paste **Google Jobs / Google Search URLs**. The `q=` search text is used.

#### How many jobs can I get?

Google Jobs shows only about **10 jobs per search** and has no "next page" for automated clients. To get more, the Actor runs the related searches that Google itself offers (date and job-type slices, remote, "no degree", employers it found, seniority levels). It removes duplicates and keeps the ones that still match your filters. Broad searches in large cities typically reach **100-300 unique jobs** (in our tests, *registered nurse in Houston* gave 200 of 200 requested from 33 Google pages). Narrow searches (a niche title plus several filters) may find only 10-30. In that case the run stops once new searches stop finding new jobs, and `OUTPUT` says how many it found. **You only pay for unique jobs saved.**

### Input examples

Simple search:

```json
{
  "queries": ["software engineer"],
  "location": "New York, NY",
  "maxResults": 50
}
```

Fresh part-time jobs posted in the last week:

```json
{
  "queries": ["barista", "cashier"],
  "location": "Seattle, WA",
  "datePosted": "week",
  "jobType": "part-time",
  "maxResults": 30
}
```

Germany, in German, full-time, remote:

```json
{
  "queries": ["Softwareentwickler"],
  "location": "München",
  "country": "de",
  "language": "de",
  "jobType": "full-time",
  "remoteOnly": true
}
```

### What data you get

Fill rates are measured on 672 jobs from our final test runs (652 with description and apply links enabled), across 13 countries and 7 languages.

| Field | What it is | Filled |
|---|---|---|
| `jobId` | Google job ID (stable, used for de-duplication) | 100% |
| `title` | Job title | 100% |
| `companyName` | Employer | 100% |
| `location` | Location as Google shows it | 100% |
| `via` | Job board / site Google found it on ("LinkedIn", "Indeed", employer site ...) | 100% |
| `postedText / postedAt` | Relative date as shown ("3 days ago") and calculated date (YYYY-MM-DD) | 85% |
| `jobType` | Full-time, Part-time, Contractor, Internship ... | 99% |
| `salary` | Salary as shown ("$120K–$150K a year") | 38% |
| `salaryMin / salaryMax / salaryCurrency / salaryPeriod` | Parsed salary numbers, ISO currency, hour/day/week/month/year | 38% |
| `qualification` | e.g. "No degree mentioned", "Bachelor's degree" | 47% |
| `benefits` | e.g. "Health insurance", "Paid time off" | 35% |
| `description` | Job description (full text, or a preview where Google only shows one, see descriptionIsPreview) | 100% |
| `highlights` | Sections such as Qualifications / Responsibilities / Benefits with bullet points | 57% |
| `applyUrl` | First "Apply on ..." URL (direct link to the job board or employer) | 100% |
| `applyLinks` | All apply options: source, url, domain (avg 3.7 per job) | 100% |
| `shareLink` | Google Jobs link to this exact job | 100% |
| `companyLogoUrl` | Employer logo | 67% |
| `searchQuery / googleQuery / position` | Your query, the exact Google search that found the job, and its order | 100% |
| `country / language / scrapedAt` | Settings used and scrape time | 100% |

`postedAt` is calculated from Google's relative date ("3 days ago") at scrape time, so it is accurate to about a day. Turning off *Include job description* or *Include apply links* drops those fields. The price is the same.

### Output example (shortened)

```json
{
  "jobId": "_QNkGauliwHHe4OMAAAAAA==",
  "title": "Software Engineer (Mid-Level)",
  "companyName": "Brean Capital, LLC",
  "location": "New York, NY",
  "via": "Indeed",
  "postedText": "5 days ago",
  "postedAt": "2026-10-22",
  "jobType": "Full-time",
  "salary": "$110K–$130K a year",
  "salaryMin": 110000,
  "salaryMax": 130000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "qualification": "No degree mentioned",
  "benefits": [
    "Dental insurance",
    "Health insurance"
  ],
  "description": "Software Engineer (Mid-Level)\nCompany: Brean Capital, LLC\nLocation: New York, NY (Midtown Manhattan)\nJob Type: Full-time\nWork Model: Hybrid (3 days per week in the office)\nExperience Level: Mid-level\nTo apply, please ema...",
  "descriptionIsPreview": false,
  "highlights": [
    {
      "title": "Qualifications",
      "items": [
        "Core Technical Stack: 3+ years of professional experience working with C# and ASP",
        "NET Core"
      ]
    },
    {
      "title": "Benefits",
      "items": [
        "Work Model: Hybrid (3 days per week in the office)",
        "Competitive base salary commensurate with experience"
      ]
    }
  ],
  "applyUrl": "https://www.indeed.com/viewjob?jk=2f463a74d9025996",
  "applyLinks": [
    {
      "source": "Indeed",
      "url": "https://www.indeed.com/viewjob?jk=2f463a74d9025996",
      "domain": "indeed.com"
    },
    {
      "source": "Glassdoor",
      "url": "https://www.glassdoor.com/job-listing/jv?jl=1010303874324",
      "domain": "glassdoor.com"
    }
  ],
  "shareLink": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer+jobs+in+New+York,+NY&htidocid=_QNkGauliwHHe4OMAAAAAA%3D%3D&hl=en-US",
  "companyLogoUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTNJW40BuQ3ypPeYHMVsz8qIOWAfHTmoAm0MM1_&s=0",
  "searchQuery": "software engineer",
  "googleQuery": "software engineer jobs in New York, NY",
  "position": 1,
  "country": "us",
  "language": "en",
  "scrapedAt": "2026-10-27T07:54:05.863Z"
}
```

### Run summary (OUTPUT record)

Each query gets one status: `SUCCEEDED`, `PARTIAL`, `NO_DATA` (Google Jobs has no results) or `FAILED`. The summary also includes the job count, the number of Google pages used, how many jobs your filters removed, a note when fewer jobs exist than you asked for, and network statistics. If every query fails, the run is marked as failed, so you never get an empty "successful" run.

### Pricing

Pay per event, no subscription. The Google SERP proxy is included:

| Event | Price | When |
|---|---|---|
| Actor start | $0.005 per GB of memory ($0.005 at the default 512 MB) | Once per run |
| Job | $0.003 | Every unique job saved to the dataset |

That is **$3 per 1,000 jobs**, plus the start fee. Duplicates are never charged. A query with no results costs only the start fee. Apify's "Maximum cost per run" is respected, and the scraper stops cleanly when it is reached.

Examples: 50 jobs ≈ $0.155 in about 1 minute. 200 jobs for one query ≈ $0.605 in about 3 minutes.

### FAQ

**Do I need a Google account, cookies or my own proxy?** No. Keep the default proxy setting (Google SERP proxy). It is included in the price.

**Can I scrape other countries and languages?** Yes. Set `country` and `language`. Filters are translated using Google's own localized filter chips. Results then come in that language, e.g. `postedText: "vor 3 Tagen"`.

**Why is `description` sometimes marked `descriptionIsPreview: true`?** For some postings (mostly outside English-speaking countries), Google shows only a short preview of the description. We return what Google shows and flag it.

**Why do apply URLs sometimes point to job boards instead of the employer?** They are exactly the "Apply on ..." options Google lists, in Google's order. The first one is in `applyUrl`.

### Limits and honest caveats

- **About 10 jobs per Google search.** Larger result sets come from related searches (see above). Very narrow searches cannot reach a high `maxResults`.
- **Filters are Google's filters.** Date and job-type filters are also checked again on the parsed data (English job types; posting dates in any language). The remote filter relies on Google's "Remote" chip.
- **Salary and qualification** appear only when Google shows them. Many postings have none (see fill rates).
- **Speed**: about 2-6 seconds per Google page. One query with 10-20 jobs takes about 15-40 seconds, and 200 jobs take about 3 minutes.
- **Test results**: In our final test, 32 of 32 runs passed (672 jobs, 13 countries, 7 languages, filters, URL input, empty and invalid input). The median run took 20 seconds. All 2,438 apply links were direct links to the job board or employer, with no Google redirects.

# Actor input Schema

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

Each entry is one search, exactly like typing into Google: e.g. "nurse", "data analyst", "barista part time". English queries get "jobs" appended automatically when missing. You can also include a place in the query itself. Required unless you paste Google URLs below.

## `googleJobsUrls` (type: `array`):

Optional. Paste Google search URLs (e.g. https://www.google.com/search?q=teacher+jobs+in+Boston\&udm=8). The q= search text is used as a query; the other settings below still apply.

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

City, region or country added to every query ("in New York, NY"). Leave empty to search without a place (Google then uses the country below).

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

Two-letter country code Google localizes results for: us, gb, de, fr, in, ca, au, es, it, nl, br, mx ... Combine with Location for the best results.

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

Interface/result language code: en, de, fr, es, it, pt, nl ... Filters are translated automatically using Google's own localized filter chips.

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

Uses Google's date filter, plus a safety post-filter on the parsed posting date.

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

Uses Google's employment-type filter.

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

Uses Google's "Remote" filter chip.

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

Google Jobs shows about 10 jobs per search, so for more the Actor runs related searches Google itself suggests (date and job-type slices, employers it found, seniority) and removes duplicates. Broad queries in big cities usually reach 100-300 unique jobs; narrow ones fewer. You pay only for unique jobs saved.

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

Full description text (when Google shows it) and the highlights (Qualifications, Responsibilities, Benefits). Turn off for smaller datasets. Same price.

## `includeApplyLinks` (type: `boolean`):

All "Apply on ..." options with direct URLs to the job boards / employer site. Same price.

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

How many Google pages are fetched at the same time.

## `maxRetries` (type: `integer`):

Google sometimes returns a page without the Jobs panel; it is retried with a new proxy connection.

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

Keep the default Google SERP proxy - it is included in the price and is what makes the Actor reliable. Other proxies are usually blocked by Google.

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "location": "New York, NY",
  "country": "us",
  "language": "en",
  "datePosted": "any",
  "jobType": "any",
  "remoteOnly": false,
  "maxResults": 20,
  "includeDescription": true,
  "includeApplyLinks": true,
  "maxConcurrency": 5,
  "maxRetries": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

## `jobs` (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"
    ],
    "location": "New York, NY",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("atlasdata/google-jobs-scraper-reliable").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",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

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

```

## MCP server setup

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

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/tnXGjbbOwi3NAff07/builds/2qJZ3LGmS2GbaqiIU/openapi.json
