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

Scrape job listings from Google Jobs: title, company, location, source board, posting date, employment type, parsed salary, remote flag, full description, highlights and direct apply links, for any query, country and language.

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

## Pricing

$3.00 / 1,000 job results

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 Scraper** extracts job listings from [Google Jobs](https://www.google.com/search?q=jobs\&udm=8), the job search built into Google Search. Google aggregates postings from LinkedIn, Indeed, Glassdoor, company career pages and hundreds of other job boards, so a single query covers many sources at once.

For each job you get the **title, company, location, source board ("via"), posting date, employment type, salary (raw text plus parsed min/max/currency/period), remote flag, full description, job highlights (qualifications, responsibilities, benefits)** and **direct apply links** for every board that lists the job.

Enter your search queries, pick a country and language, click **Start**, and download the data as JSON, CSV, Excel or HTML, or fetch it through the Apify API. Because it runs on the Apify platform, you can schedule it, call it from your own code, connect it to Make, Zapier or Google Sheets, and monitor every run.

### Why use Google Jobs Scraper?

- **Job market research.** Measure demand for roles, skills and locations, and track how it changes over time.
- **Salary benchmarking.** Collect posted salary ranges, already parsed into numbers, currency and pay period.
- **Job boards & aggregators.** Feed your own job board or newsletter with fresh listings and their original apply links.
- **Recruiting & sales intelligence.** See which companies are hiring for what, and where (company data only, no personal data).

No browser is involved: the Actor fetches Google's results pages and parses them directly, which keeps it fast and inexpensive.

### How to scrape Google Jobs

1. Open the Actor and go to the **Input** tab.
2. Add one or more **search queries**, for example `software engineer`, `registered nurse` or `enfermeiro`.
3. Optionally add a **location** (`Berlin`, `São Paulo`, `Remote`...), then set the **country**, **language** and **date posted** filter.
4. Choose how many jobs you want per query.
5. Click **Start**. When the run finishes, open the **Output** tab or export the dataset.

### Input

All fields except `queries` are optional.

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | string\[] | (required) | Job searches, exactly as you would type them on Google. One search per query. |
| `location` | string | none | City, region or `Remote`, appended to every query. |
| `country` | string | us | Google market (`gl`), e.g. `us`, `br`, `de`, `in`, `gb`. |
| `language` | string | en | Interface language (`hl`), e.g. `en`, `pt-BR`, `de`. Labels such as "3 days ago" or "Full-time" come in this language. |
| `datePosted` | enum | any | `any`, `today`, `3days`, `week` or `month`. |
| `maxResultsPerQuery` | integer | 50 | Maximum jobs per query (1 to 300). |
| `proxyConfiguration` | object | Apify Proxy, GOOGLE\_SERP | Google only serves real results to the GOOGLE\_SERP proxy group. Keep the default. |

Example input:

```json
{
    "queries": ["software engineer", "data analyst"],
    "location": "Berlin",
    "country": "de",
    "language": "en",
    "datePosted": "week",
    "maxResultsPerQuery": 100
}
```

### Output

One item per job. Example (description shortened):

```json
{
    "query": "software engineer",
    "searchLocation": null,
    "rank": 3,
    "title": "Software Engineer I",
    "company": "Example Tech Solutions",
    "location": "United States",
    "via": "LinkedIn",
    "postedAt": { "raw": "12 hours ago", "iso": "2026-09-28T17:37:07.951Z" },
    "employmentType": "Contractor",
    "salary": { "raw": "50–80 an hour", "min": 50, "max": 80, "currency": "USD", "period": "hour" },
    "isRemote": true,
    "description": "1 Year Contract\nRemote Role\n\nSummary:\n• ...",
    "descriptionIsPreview": false,
    "highlights": [
        { "title": "Qualifications", "items": ["3+ years of Python", "Experience with deep learning codebases"] },
        { "title": "Responsibilities", "items": ["Work with research teams on training infrastructure"] }
    ],
    "applyLinks": [
        { "source": "LinkedIn", "url": "https://www.linkedin.com/jobs/view/..." },
        { "source": "BeBee", "url": "https://bebee.com/us/jobs/..." }
    ],
    "jobId": "jTCjYq3ePxHPx-HGAAAAAA==",
    "googleJobUrl": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer&htidocid=jTCjYq3ePxHPx-HGAAAAAA%3D%3D&hl=en-US",
    "companyLogo": "https://encrypted-tbn0.gstatic.com/images?q=tbn:...",
    "country": "us",
    "language": "en",
    "scrapedAt": "2026-09-29T05:37:07.951Z"
}
```

#### Data fields

| Field | Description |
|---|---|
| `title`, `company`, `location` | The job and the hiring company as shown by Google |
| `via` | The job board or site Google took the listing from (LinkedIn, Indeed, company careers site...) |
| `postedAt.raw`, `postedAt.iso` | Posting age as shown ("3 days ago", "vor 5 Tagen") and the derived ISO date (date-time for hours/minutes), relative to `scrapedAt` |
| `employmentType` | Full-time, Part-time, Contractor, Internship... (in the chosen language) |
| `salary` | `raw` text plus parsed `min`, `max`, `currency` (ISO code) and `period` (`hour`, `day`, `week`, `month`, `year`); `null` when Google shows no salary |
| `isRemote` | `true` when Google marks the job as "Work from home" or the location/title says remote/anywhere |
| `description`, `descriptionIsPreview` | Full job description with line breaks. In EU markets Google only shows a short preview; then `descriptionIsPreview` is `true` |
| `highlights[]` | Google's job highlights: `{ title, items[] }`, e.g. Qualifications, Responsibilities, Benefits |
| `applyLinks[]` | `{ source, url }` for every place you can apply, with the direct URL (not a Google redirect) |
| `jobId`, `googleJobUrl`, `companyLogo` | Google Jobs document id, a link that opens the job on Google, company logo thumbnail |
| `query`, `searchLocation`, `rank`, `country`, `language`, `scrapedAt` | Search context |

Queries that return no jobs produce one item with `query` and an `error` message. Those items are free.

### How much does it cost to scrape Google Jobs?

This Actor uses **pay-per-event** pricing. You only pay for jobs you get:

| Event | Price | When |
|---|---|---|
| `job` | $0.003 | per job returned ($3 per 1,000 jobs) |

Platform usage is included in the price. Queries that return nothing are never charged, and the run stops cleanly when it reaches your maximum cost per run.

### How does it get more than 10 jobs per query?

Google shows 10 jobs per results page and loads the rest through a browser session. Instead of a browser, the Actor walks Google's own filters for your query: **job type** (full-time, part-time, contract, internship), **date posted**, **remote** and **no degree**, plus their combinations, and removes duplicates by job id. Broad queries usually reach 100 to 300 unique jobs; very narrow ones stop when Google has nothing new. Results are in Google's relevance order within each filter, so `rank` is the order in which the Actor found the job.

### Tips

- Use `maxResultsPerQuery` to cap cost and run time.
- Put the city in `location` (or in the query) to get local jobs; `country` alone sets the Google market.
- Use `datePosted: "today"` in a daily schedule to collect only new postings.
- In EU markets (e.g. `country: "de"` or `"fr"`) Google shows only a short description preview and no highlights. If you need full descriptions for a European city, try `country: "us"` with `location: "Berlin"`: the jobs are the same local postings, shown with their full text.

### Limitations

- Results are what Google shows to an anonymous visitor in the chosen market; they can differ from your personalized view.
- Salary, highlights and employment type are only present when Google provides them for that listing.
- Posting dates are relative ("3 days ago"), so `postedAt.iso` is approximate (±1 day; "30+ days ago" becomes 30 days).
- Descriptions are scrubbed of email addresses and phone numbers. The Actor returns job and company data only.

### FAQ

**Is it legal to scrape Google Jobs?** The Actor only collects publicly visible job listings and company information. It removes contact details from descriptions, doesn't collect personal data and doesn't log in. You're responsible for how you use the data: check the terms of the sites involved and the laws that apply to you.

**Something is broken or missing?** Please open an issue in the **Issues** tab with the input you used. We fix problems quickly.

# Actor input Schema

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

Job searches exactly as you would type them on Google, e.g. "software engineer" or "enfermeiro". One Google Jobs search per query.

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

Optional city, region or "Remote" added to every query, e.g. "São Paulo", "Berlin" or "Remote".

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

Two-letter country code of the Google market to search (gl), e.g. us, br, de, in, gb.

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

Interface language (hl), e.g. en, pt-BR, de. Affects labels such as "3 days ago" or "Full-time".

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

Only return jobs posted within this period.

## `maxResultsPerQuery` (type: `integer`):

Maximum number of jobs to return for each query. Google shows 10 jobs per results page; to go further the Actor walks Google's own filters (job type, date posted, remote, no degree and their combinations) and removes duplicates, so very broad queries can reach 300 while narrow ones stop earlier.

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

Google Search only serves real results to Apify's GOOGLE\_SERP proxy group (other proxies get a JavaScript challenge or a CAPTCHA), so keep the default unless you know what you are doing.

## Actor input object example

```json
{
  "queries": [
    "software engineer"
  ],
  "country": "us",
  "language": "en",
  "datePosted": "any",
  "maxResultsPerQuery": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

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

Dataset with one item per job (plus error items for queries that returned nothing)

## `summary` (type: `string`):

Per-query job counts and errors

# 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"
    ],
    "country": "us",
    "language": "en",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

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

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

```

## MCP server setup

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

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/vsZGi3RFocL0y47x9/builds/eAxbjtyeZB6sRAk1z/openapi.json
