# Google Jobs Scraper (`dami_studio/google-jobs-scraper`) Actor

Extract structured Google Jobs listings with stable IDs, employer, location, source, apply URLs, dates, salary, and job details when available. Direct-first with bounded browser fallback.

- **URL**: https://apify.com/dami\_studio/google-jobs-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 job listings

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Jobs Scraper

Search the public Google Jobs experience and return one structured dataset row per listing. The actor returns stable job IDs (Google `htidocid`), title, company, location, source board, the Google listing URL, posting date when shown, employment type when shown, and the apply channels offered for the listing.

> **Since 2026 Google requires JavaScript for `/search`**, so a plain HTTP request returns an "Enable JavaScript to use search" gate from any address; this is reported as `JS_REQUIRED`, not as a block, and `enableProxyFallback` is on by default so the Google SERP lane can serve the job cards. Google also stopped putting apply links in the served HTML - `applyUrl` is `null` on the HTTP transports, `applyOptions` lists the boards by name, and `googleJobUrl` links to the listing page that carries the working apply buttons.

### Input

| Field | Description |
| --- | --- |
| `query` | Job title, skill, or keywords such as `software engineer`. |
| `location` | Optional city, region, country, or remote location. |
| `country` / `language` | Google regional and language settings. |
| `maxItems` | 1-100 unique jobs, default 25. |
| `maxScrolls` | Browser scroll rounds, 0-8, default 3. |
| `deadlineSeconds` | Wall-clock limit, 20-180 seconds, default 90. |
| `enableProxyFallback` | Disabled by default. Routes the browser fallback through rotating datacenter proxy addresses after direct access is blocked. |
| `proxyConfiguration` | Optional. Your own servers in `proxyUrls` are used exactly as given. Metered per-gigabyte groups (`RESIDENTIAL`, `GOOGLE_SERP`) are not offered and are replaced with rotating datacenter addresses. |

### Output

Each successful row has `ok: true`, `jobId`, `title`, `company`, `location`, `source`, `applyUrl`, and search metadata. `datePosted`, `salary`, `description`, and `employmentType` are nullable because Google does not display them for every listing. Rows are deduplicated by Google's ID when present, otherwise by a stable hash of title, employer, location, and URL.

### Transport and proxy behavior

The actor first sends a direct HTTP request to Google. Google commonly returns a JavaScript shell without job data to non-browser HTTP clients, so the actor then renders the same public Jobs search with Playwright. Direct browser rendering is attempted without a proxy. If Google blocks that request and `enableProxyFallback` is enabled, the actor retries through a rotating datacenter proxy session within the request and wall-time bounds. Proxy use is never implicit.

Metered per-gigabyte proxy groups are not offered. A `proxyConfiguration` asking for `RESIDENTIAL` or `GOOGLE_SERP` is served with rotating datacenter addresses instead, and the substitution is written to the log, to the run status message, and to the `proxyNotice` field of any diagnostic row. If you need different exit addresses, put your own proxy servers in `proxyConfiguration.proxyUrls`; those are passed through untouched and take precedence over everything else.

### Billing

`$0.01` to start a run, then `$0.0015` per job — `$1.50` per 1,000 jobs.

One `job` event is charged only after a complete job row has been written. Empty input returns one uncharged `_sample` row, and empty results, blocks, rate limits, network errors and incomplete rows all produce uncharged diagnostics. A search that finds nothing therefore costs the start charge and nothing else.

### Set `country` to match your `location`

`country` defaults to `US`. Asking for a `location` in another country while leaving it at the default is the one mistake that reliably returns nothing — "Berlin" on the US edition comes back empty, while "Berlin" with `country: "DE"` returns a full page of jobs. Set both together.

Confirmed working: `US`, `GB`, `DE`, `FR`, `ES`, `CA`. Australia and Ireland currently come back empty — Google answers those editions with its JavaScript gate instead of job cards, and there is nothing this actor can do about that from the server side. Try one search before you plan a large run against a country not on that list.

### Example

```json
{
  "query": "software engineer",
  "location": "Toronto",
  "country": "CA",
  "maxItems": 25,
  "maxScrolls": 3,
  "deadlineSeconds": 90,
  "enableProxyFallback": false
}
```

This actor does not use a Google API key, login, CAPTCHA solving, hidden-email access, or job-board credentials.

# Actor input Schema

## `query` (type: `string`):

Job title, skills, or keywords to search for, for example software engineer or registered nurse.

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

Optional city, region, country, or remote location to bias the Google Jobs search.

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

Two-letter Google country code used for regional results, such as US, CA, or GB.

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

Google interface language code, such as en, fr, or de.

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

Maximum number of unique job rows to return. Requests are bounded to 100 rows and 8 scroll rounds.

## `maxScrolls` (type: `integer`):

Maximum browser scroll rounds used to load more jobs after the first page, from 0 to 8.

## `deadlineSeconds` (type: `integer`):

Maximum wall-clock seconds for the complete scrape, from 20 to 180 seconds.

## `enableProxyFallback` (type: `boolean`):

Retry through the proxy lanes when the direct request cannot be read. Google now serves its "Enable JavaScript to use search" gate to every plain-HTTP client on every address, so the direct lane alone returns no job cards and this must stay on for the Actor to produce rows.

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

Optional proxy configuration used only when proxy fallback is enabled and direct access is blocked. Metered per-gigabyte groups (RESIDENTIAL, GOOGLE\_SERP) are not offered and are replaced with rotating datacenter addresses. To use different addresses, supply your own servers in proxyUrls; those are used exactly as given.

## Actor input object example

```json
{
  "query": "software engineer",
  "location": "",
  "country": "US",
  "language": "en",
  "maxItems": 25,
  "maxScrolls": 3,
  "deadlineSeconds": 90,
  "enableProxyFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "BUYPROXIES94952"
    ]
  }
}
```

# Actor output Schema

## `jobs` (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 = {
    "query": "software engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = { "query": "software engineer" }

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

```

## MCP server setup

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