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

Scrape Google Jobs listings for any search and location: title, company, salary, full description, posted date and every apply link (LinkedIn, Indeed, company site). Pay only per job, never for empty pages.

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

## Pricing

from $2.50 / 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: Listings, Salaries & Apply Links

Scrape Google Jobs listings for any job search and location: title, company, location, salary
(parsed into min/max/currency/period), posted date, employment type, full description, job
highlights and **every apply link** (LinkedIn, Indeed, ZipRecruiter, the company's own careers
page…) as real URLs. Pay only per job delivered, never for empty or blocked pages. Export to JSON,
CSV or Excel, or call it from your code, Make, Zapier, n8n, or an AI agent via MCP.

### What data can you get?

| Field | Example |
|---|---|
| `title` | Senior Software Engineer - Enterprise Architecture & AI Solutions Engineering |
| `company` | Charles Schwab |
| `location` | Austin, TX |
| `via` | Schwab Jobs |
| `postedAgo` / `postedAt` | 15 days ago / 2026-09-14T17:30:00.000Z |
| `employmentType` / `employmentTypes` | Full-time / `["FULL_TIME"]` |
| `salaryText` | $150K–$185K a year |
| `salaryMin` / `salaryMax` / `salaryCurrency` / `salaryPeriod` | 150000 / 185000 / USD / year |
| `benefits` | Dental insurance, Paid time off, Health insurance |
| `highlights` | Qualifications, Benefits, Responsibilities (bullet lists) |
| `description` | Full job description text |
| `applyLinks` | `[{ source: "LinkedIn", url: "https://www.linkedin.com/jobs/view/…", isDirect: false }, …]` |
| `applyUrl` | The first apply option (usually the "via" source) |
| `googleJobUrl` | Opens the job in Google Jobs |
| `jobId` | Google's job id, stable across runs, for de-duplication |
| `isRemote`, `companyLogo`, `searchQuery`, `searchLocation`, `rank`, `scrapedAt` | |

<details><summary>Sample output (1 item, long lists shortened with …)</summary>

```json
{
    "jobId": "qI6PcOLQJzlMANrUAAAAAA==",
    "title": "Senior Software Engineer - Enterprise Architecture & AI Solutions Engineering",
    "company": "Charles Schwab",
    "location": "Austin, TX",
    "via": "Schwab Jobs",
    "postedAgo": "15 days ago",
    "postedAt": "2026-09-14T17:30:00.000Z",
    "employmentType": "Full-time",
    "employmentTypes": ["FULL_TIME"],
    "isRemote": false,
    "salaryText": "$150K–$185K a year",
    "salaryMin": 150000,
    "salaryMax": 185000,
    "salaryCurrency": "USD",
    "salaryPeriod": "year",
    "benefits": ["Dental insurance", "Paid time off", "Health insurance"],
    "highlights": [
        {
            "title": "Qualifications",
            "items": [
                "Bachelor’s or Master’s degree in Computer Science or equivalent professional experience",
                "Demonstrated senior-level engineering depth through hands-on ownership of full-stack systems shipped end to end",
                "…"
            ]
        },
        { "title": "Benefits", "items": ["In addition to the salary range, this role is eligible for bonus or incentive opportunities", "…"] },
        { "title": "Responsibilities", "items": ["…"] }
    ],
    "description": "Your opportunity\n\nAt Schwab, you’re empowered to make an impact on your career. Here, innovative thought meets creative problem solving, helping us challenge the status quo and transform the finance industry together. …",
    "applyLinks": [
        {
            "source": "Schwab Jobs",
            "url": "https://www.schwabjobs.com/job/austin/senior-software-engineer-enterprise-architecture-and-ai-solutions-engineering/33727/98059247040?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
            "isDirect": false
        },
        {
            "source": "LinkedIn",
            "url": "https://www.linkedin.com/jobs/view/senior-software-engineer-enterprise-architecture-ai-solutions-engineering-at-charles-schwab-4441822205?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
            "isDirect": false
        },
        "…"
    ],
    "applyUrl": "https://www.schwabjobs.com/job/austin/senior-software-engineer-enterprise-architecture-and-ai-solutions-engineering/33727/98059247040?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
    "googleJobUrl": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer+jobs+austin&htidocid=qI6PcOLQJzlMANrUAAAAAA%3D%3D&…",
    "companyLogo": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjLZJv0c4eUiAPTL24rSh52v-541rhsjwKrZ1E&s=0",
    "searchQuery": "software engineer",
    "searchLocation": "Austin, TX",
    "rank": 8,
    "scrapedAt": "2026-09-29T17:30:00.000Z"
}
```

</details>

### Why this scraper

| | This Actor |
|---|---|
| Charged for empty searches, blocked pages or duplicates | **Never.** You pay per unique job delivered, nothing else except a $0.01 run start |
| More than Google's 10 jobs per search | Yes: re-runs the search with Google's own filters (job type, date posted) and keeps only new jobs |
| Duplicates | Removed across all searches and locations in a run (by Google job id, and title + company + location) |
| Apply links | Every option Google lists, as the real posting URL (not a Google redirect), with its source name |
| Salary | Raw text plus parsed min, max, ISO currency and period |
| Many searches × many locations in one run | Yes, run in parallel |
| Filters | Date posted, employment type, remote; jobs that contradict your filter are dropped, not charged |
| Browser | None: fast HTTP through Apify's Google SERP proxy |

### How much does it cost?

Pay only for jobs delivered: **$3.50 per 1,000 jobs** plus $0.01 per run (lower on paid Apify
plans, down to $2.50 per 1,000). Examples:

- The default input (10 software engineer jobs in Austin, TX) ≈ **$0.05**.
- 10 searches × 50 jobs (500 jobs) ≈ **$1.76**.
- A daily "posted since yesterday" check that finds 40 new jobs ≈ **$0.15**.

A search that finds nothing costs nothing beyond the run start. Set **Max jobs per search** to cap
what you spend; the run also stops cleanly at the maximum total charge you set for a run.

### How to use it

1. Add one or more **Job searches**, as you would type them into Google (`software engineer`,
   `registered nurse`, `barista part time`).
2. Optionally add **Locations** (`Austin, TX`, `London`, `Berlin`). Every search runs in every
   location.
3. Set **Max jobs per search and location**, and optionally **Date posted**, **Employment type**
   and **Remote**.
4. For other countries, set **Country** (`gb`, `de`, `ca`, `in`…) and **Language** (`en`, `de`…).
5. Run, then download the dataset in the format you need.

**Monitoring new jobs:** schedule a daily run with Date posted = Since yesterday, and use `jobId` to
skip jobs you already have.

**API:** `POST https://api.apify.com/v2/acts/tidyscrape~google-jobs-scraper/run-sync-get-dataset-items`
with your input as JSON, for example:

```json
{
    "queries": ["data analyst", "data engineer"],
    "locations": ["New York, NY", "Chicago, IL"],
    "maxJobsPerQuery": 50,
    "datePosted": "week",
    "country": "us",
    "language": "en"
}
```

**AI agents:** available through the Apify MCP server. "Find remote data engineering jobs posted
this week" maps directly to the input, and every input and output field is described.

### Use cases

- **Job boards and aggregators:** fill listings for any role and city, with the apply links.
- **Salary research:** collect pay ranges by title and location in the Salaries view.
- **Labor-market and hiring analytics:** track who is hiring for what, where, and how fast.
- **Recruiting and sales intelligence:** spot companies hiring for roles your product or agency serves.
- **Personal job search automation:** a daily feed of new matching jobs into a sheet, Slack or email.

### FAQ

**How many jobs can I get per search?** Google shows 10 jobs per search and offers no further pages
to automated access. The Actor re-runs each search with Google's own filters and keeps only new
jobs. For a broad search in a large city that is usually 50-100+ unique jobs. For more, use
more specific searches or more locations (nearby cities, neighborhoods).

**Do I pay for pages with no jobs, or for duplicates?** No. Only unique jobs delivered to your
dataset are charged. Empty searches, blocked or failed requests and duplicates cost nothing.

**Why do some jobs have no salary or posted date?** The employer did not publish one, so Google
shows none. The fields are then `null`.

**How exact are the filters?** Date posted, employment type and remote use Google's own filters.
Google's type filter is loose, so the Actor also drops jobs that Google labels with a different
type or an older date. `postedAt` is approximate (from "4 days ago"). `isRemote` is a best-effort
flag from the title, location and labels.

**Which countries and languages work?** Any country Google Jobs covers: set Country and Language.
Filters are verified for English and German. Some languages show only a description preview.

**Why does a run take a while?** Each Google request takes 15-40 seconds through Apify's Google
SERP proxy. Requests run in parallel (Parallel requests, default 5), so large runs stay fast.

**Is it legal to scrape Google Jobs?** This Actor collects job listings that Google shows publicly
in Google Search, without logging in. Job postings are business advertisements; the Actor does not
extract or enrich recruiter contact details. You are responsible for using the data lawfully
(e.g. GDPR/CCPA, the terms of the sites you link to). Not for FCRA purposes (e.g. screening
applicants). This Actor is not affiliated with or endorsed by Google.

**Something broke or a field is missing?** Open an Issue. We usually respond within a day.

### Changelog

- 2026-09-29: first release.

# Actor input Schema

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

What to search for, as you would type it into Google, e.g. "software engineer", "registered nurse" or "barista part time". Each search is run once per location. You can put the place in the search itself ("data analyst jobs in Denver") and leave Locations empty.

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

Optional places to search in, e.g. "Austin, TX", "London" or "Berlin". Each is added to every search the way Google's own location phrasing works ("software engineer Austin, TX"). Leave empty to search without a place: Google then picks jobs near the proxy's exit location, so add a location or country-wide place ("United States") for predictable results.

## `maxJobsPerQuery` (type: `integer`):

Stop after this many unique jobs for each search × location. Google shows 10 jobs per search; for more, the Actor re-runs the search with Google's own filters (job type, date posted) and keeps only new jobs, which usually yields 50-100+ unique jobs for a broad search in a big city. You pay only per job returned, so this also caps cost.

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

Only jobs posted within this period. Jobs whose age Google shows as older are dropped (and not charged).

## `employmentType` (type: `string`):

Only this type of job. Google's own filter is loose, so jobs that Google labels with a different type are dropped (and not charged), unless the title states the type (e.g. "Software Engineer Intern"). Jobs with no type label are kept.

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

Apply Google's "Remote" (work from home) filter. Results then come from anywhere in the country, not only the locations above.

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

2-letter country code Google searches from, e.g. "us", "gb", "ca", "de", "in". Match it to your locations.

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

Google interface language, e.g. "en", "de", "fr". It sets the language of labels such as "3 days ago" and "Full-time"; the job texts stay in the language they were posted in. Filters are verified for "en" and "de".

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

How many Google requests run at once across all searches. Each takes 15-40 s through Google's SERP proxy, so parallel requests make large runs much faster.

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

Keep the default: Apify's GOOGLE\_SERP proxy group, the only one that returns Google Jobs results (other proxies get a JavaScript-only page).

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxJobsPerQuery": 10,
  "datePosted": "any",
  "employmentType": "any",
  "remoteOnly": false,
  "country": "us",
  "language": "en",
  "maxConcurrency": 5,
  "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"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxJobsPerQuery": 10,
    "country": "us",
    "language": "en",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidyscrape/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": ["Austin, TX"],
    "maxJobsPerQuery": 10,
    "country": "us",
    "language": "en",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

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

```

## MCP server setup

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