# Google Jobs Scraper - Descriptions, Salary & Apply Links (`santhej/google-jobs-scraper`) Actor

Scrape Google Jobs for any role and city: title, employer, job description, salary parsed into numbers, employment type, posting date and every apply link. 75 countries, up to 200 jobs per search, date, type and remote filters. $3 per 1,000 jobs, failed queries are free. No API key.

- **URL**: https://apify.com/santhej/google-jobs-scraper.md
- **Developed by:** [Santhej Kallada](https://apify.com/santhej) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Features:** Limited permissions
- **Stats:** 9 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 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.
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 — Descriptions, Salary & Apply Links

**Scrape Google Jobs for any role and place and get every listing as a clean row: title, employer, location, the job description, salary parsed into numbers, employment type, posting date and every apply link — for $3.00 per 1,000 jobs.**

Google Jobs gathers listings from LinkedIn, Indeed, Glassdoor, company career pages and thousands of niche boards into one feed. This Actor turns any search on it into a dataset you can download or call from your own code — no browser to run, no proxies, no CAPTCHAs and no API keys.

### What does Google Jobs Scraper do?

For each search you give it — `registered nurse`, `software engineer new york`, `data analyst remote` — the Actor reads Google Jobs in the country you choose and returns one row per listing, in Google's order, up to 200 listings per search.

Each row is ready to use: the salary text is parsed into minimum, maximum, currency and pay period; the posting age ("3 days ago") becomes a date; the employment type becomes a fixed code you can filter on; and the apply links point at the job board or career page itself, not at a Google redirect.

It also gets results where a plain search does not. A job title that doubles as a local business — `dentist chicago`, `physical therapist austin` — returns nothing on Google Jobs as written; the Actor notices and searches again the way that works. Countries with no English-language listings are searched again in their own language. A search Google refuses to answer is tried a second time. And you never pay for a query that failed.

### What you get per job

| Field | What it tells you | How often it is filled |
|---|---|---|
| `title` | Job title | Always |
| `employer_name` | Hiring company | Always |
| `location` | City / region, or `Anywhere` for remote roles | Always |
| `is_remote` | `true` when Google lists the job's location as "Anywhere" (recognised in English, German and Portuguese results) | Always |
| `description` | The job description as plain text with line breaks. Full text outside the EU; in EU countries Google only publishes a preview of about 400 characters | Always |
| `qualifications`, `responsibilities`, `benefits` | Google's "Job highlights" as lists | United States listings |
| `apply_options` | Every site the job can be applied on: `title` (LinkedIn, Indeed, the company's own careers page…), direct `url`, and `is_direct` | Always |
| `tags` | The labels Google shows under the title, as displayed: `3 days ago`, `Full-time`, `Health insurance`, `Paid time off`, `No degree mentioned`… | Almost always |
| `source_name`, `source_url` | The first site Google lists for the job and its link | Always |
| `salary` | Pay exactly as displayed, e.g. `$85K–$125K a year` | When the listing shows pay — from about a quarter of listings to most of them, depending on the role |
| `salary_min`, `salary_max`, `salary_currency`, `salary_period` | The same pay as numbers (`85K` becomes `85000`), a currency code and `hour` / `day` / `week` / `month` / `year` | With `salary` |
| `contract_type` | Employment type as Google shows it, e.g. `Full-time`, `Part-time and Contractor`, `Vollzeit` | Almost always |
| `employment_types` | The same as fixed codes — `FULLTIME`, `PARTTIME`, `CONTRACTOR`, `INTERN` — for listings in English, German, French, Spanish, Italian, Portuguese, Dutch and Japanese | Almost always in those languages |
| `posted`, `posted_at` | Posting age as shown (`1 day ago`) and as a date (`YYYY-MM-DD`) | When Google shows it (most listings) |
| `employer_image_url` | The employer's logo | When Google shows one |
| `job_id` | Google's identifier for the listing — use it to de-duplicate across runs | Always |
| `rank` | Position in the Google Jobs results | Always |
| `query`, `country`, `language`, `checked_at` | Exactly which search the row came from, and when | Always |

`employer_url` is kept for compatibility with earlier versions and is usually empty, because Google Jobs does not show the employer's website in its results.

A run summary — queries searched, jobs returned, jobs removed by your filters and the billing breakdown — is saved to the key-value store as `OUTPUT`.

### Use cases

- **Job boards and aggregators** — fill a niche board with fresh listings, descriptions and apply links, refreshed on a schedule.
- **Recruiting and staffing** — see who is hiring for the roles you place, city by city, the day the job is posted.
- **Salary benchmarking** — compare advertised pay by role, region and employment type with ready-made numbers.
- **Sales prospecting** — a company that is hiring has budget and a problem to solve; use new listings as a buying signal.
- **Labour-market research** — track demand for a skill or a job title over time and across countries.
- **AI agents and RAG pipelines** — full job descriptions and qualifications as structured context for an LLM.

### How to use

1. Add one or more **Job search queries** — each is a separate search. A role plus a place works best (`registered nurse london`).
2. Optionally put a **City or region** in its own field; it is added to every query.
3. Choose the **Country** and how many **Results per query** you want (10–200).
4. Optionally limit by **Date posted**, **Employment type** or **Remote only**.
5. Click **Start**, then export the dataset as JSON, CSV or Excel, or read it through the Apify API.

For a daily feed of new jobs, schedule the Actor once a day with **Date posted** set to *Today* and de-duplicate on `job_id`.

#### Example input

```json
{
  "queries": ["registered nurse", "physical therapist"],
  "location": "Austin, TX",
  "resultsDepth": 30,
  "locationCode": "2840",
  "languageCode": "en",
  "datePosted": "3days"
}
```

#### Input configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | array of strings | — (required) | Job searches, up to 100 per run. Duplicates are removed. |
| `location` | string | — | City or region added to every query, e.g. `Austin, TX`. Leave empty when the queries already name the place. |
| `resultsDepth` | integer | `20` | Listings to return per query, 10–200. |
| `locationCode` | string | `2840` (United States) | Country to search. 75 countries are selectable in the form, among them `2826` United Kingdom, `2124` Canada, `2356` India, `2276` Germany, `2250` France, `2724` Spain, `2380` Italy, `2392` Japan, `2528` Netherlands, `2076` Brazil, `2702` Singapore, `2784` United Arab Emirates. |
| `languageCode` | string | `en` | Two-letter language of the search. If nothing is found in it, the search is repeated once in the country's own language. |
| `datePosted` | string | `all` | `all`, `today`, `3days`, `week` or `month`. Keeps only jobs whose posting age falls in the window; jobs that show no posting date are left out while a window is set. |
| `employmentType` | array | all types | Any of `FULLTIME`, `PARTTIME`, `CONTRACTOR`, `INTERN`. Keeps only jobs whose listing shows one of the selected types. |
| `workFromHome` | boolean | `false` | Remote only: adds "remote" to each search so Google Jobs returns work-from-home listings. |
| `includeJobDetails` | boolean | `true` | Adds `description`, `qualifications`, `responsibilities`, `benefits`, `tags` and `apply_options` to each row at no extra charge. Turn off for smaller rows. |

**How the filters work.** *Today* and *Last 3 days* are asked of Google itself — in English, German, French, Spanish, Italian and Portuguese searches, and for *Last 3 days* also in Dutch and Japanese — so the search returns only fresh listings and you get a full page of them. *Past week*, *Past month*, a choice of several employment types, and every filter in other languages are checked on each listing after it is fetched, so such a query can return fewer rows than **Results per query**. Either way, every listing is checked against your filters, a listing they remove is never charged, and the log says how many were removed.

#### Example output

A real row from a `software engineer new york` search in the United States. The description (11,109 characters in the dataset) and the lists (20 qualifications, 36 responsibilities, 11 benefits, 8 apply options) are shortened here:

```json
{
  "query": "software engineer new york",
  "title": "Principal, Software Engineer - Enterprise Automation Frameworks & Support",
  "employer_name": "Humana",
  "employer_url": null,
  "employer_image_url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQgOu6HpymOdadnLr_Gc4eUo29W0ET9IQfkIxKD&s=0",
  "location": "Anywhere",
  "salary": "$157K–$215K a year",
  "salary_min": 157000,
  "salary_max": 215000,
  "salary_currency": "USD",
  "salary_period": "year",
  "contract_type": "Full-time",
  "source_name": "via LinkedIn",
  "source_url": "https://www.linkedin.com/jobs/view/principal-software-engineer-enterprise-automation-frameworks-support%E2%80%8B-at-humana-4475782911",
  "posted": "4 days ago",
  "posted_at": "2026-10-08",
  "job_id": "3lS_BPUV4ZU_lLQGAAAAAA==",
  "rank": 6,
  "employment_types": [
    "FULLTIME"
  ],
  "is_remote": true,
  "description": "Become a part of our caring community\n\nHumana is committed to helping people achieve their best health by delivering innovative technology solutions that power exceptional member and provider experiences.\n\nPrincipal Automation Engineer, Enterprise Automation Frameworks & Support is a senior technical leader …",
  "qualifications": [
    "Define and implement AI-enabled testing strategies, tools, and practices across the organization",
    "Partner with engineering teams to integrate AI capabilities into quality engineering workflows and delivery pipelines",
    "Drive innovation through intelligent automation and predictive quality analytics"
  ],
  "responsibilities": [
    "This role serves as the enterprise automation authority across Humana's business segments, partnering closely with Engineering, Architecture, DevOps, Product, and Quality Engineering teams to accelerate software delivery through modern automation and intelligent quality practices",
    "Principal Automation Engineer, Enterprise Automation Frameworks & Support will lead the adoption of automation-first testing approaches, establish enterprise standards and frameworks, drive AI-enabled testing innovations, and provide technical leadership for quality engineering transformation initiatives",
    "This individual will be responsible for designing scalable automation solutions leveraging technologies such as Selenium, Playwright, REST Assured , Tricentis Tosca, Azure DevOps (ADO), qTest, API automation frameworks, CI/CD pipelines, and AI-powered testing agents, while enabling delivery teams to achieve greater speed, reliability, and quality"
  ],
  "benefits": [
    "Scheduled Weekly Hours",
    "Pay Range",
    "The compensation range below reflects a good faith estimate of starting base pay for full time (40 hours per week) employment at the time of posting"
  ],
  "tags": [
    "4 days ago",
    "157K–215K a year",
    "Full-time",
    "Dental insurance",
    "Paid time off",
    "Health insurance"
  ],
  "apply_options": [
    {
      "title": "LinkedIn",
      "url": "https://www.linkedin.com/jobs/view/principal-software-engineer-enterprise-automation-frameworks-support%E2%80%8B-at-humana-4475782911",
      "is_direct": false
    },
    {
      "title": "Indeed",
      "url": "https://www.indeed.com/viewjob?jk=e9ba44ef9ded44b0",
      "is_direct": false
    },
    {
      "title": "JobLeads",
      "url": "https://www.jobleads.com/us/job/principal-software-engineer-enterprise-automation-frameworks-support--new-york--ec113c8bd8562667b645f0e7cead291b2",
      "is_direct": false
    }
  ],
  "country": "us",
  "language": "en",
  "checked_at": "2026-10-12T07:52:18.969Z"
}
```

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

Pay per event. No monthly fee, no setup fee, and you never pay for a query that failed.

| Event | Price (Free and Bronze plans) |
|---|---|
| Actor start | $0.001 per run |
| Job listing returned | **$0.003 per job — $3.00 per 1,000** |

Apify Silver plans get 10% off these prices and Gold plans and above 20% off. The description, highlights, apply links and logo are included in the price of the job.

- One query, 20 jobs: $0.001 + 20 × $0.003 = **$0.061**.
- Five queries, 20 jobs each (100 rows): **$0.301**.
- Ten queries, 100 jobs each (up to 1,000 rows): **up to $3.001**.

You pay per job actually returned. Each search has a small fixed cost of its own, so a run whose searches return almost nothing after your filters — for example 100 listings fetched and a single one left by a *Past week* filter — is billed some extra units (12 in that example, $0.036); the run summary shows them as `minimum_charge_units_added`. On an ordinary run that number is 0. A query with no results adds nothing beyond the start fee.

### FAQ

**Do I need an API key or a proxy?** No. Add your searches and run — everything else is handled for you.

**Why did I get fewer jobs than I asked for?** Either Google Jobs has fewer listings for that search — a narrow role in a small town may have a dozen — or your Date posted / Employment type filters removed some. You are charged only for the jobs returned.

**Which countries are supported?** The 75 countries in the Country list. Each one was tested and returned listings. Australia, New Zealand, Ireland, Mexico and South Korea are among the countries that are not available.

**Do I get the full job description?** In the United States, United Kingdom, Canada, India, Singapore, Japan, Brazil, South Africa, the Philippines and the United Arab Emirates, yes — the whole text. In EU countries (Germany, France, Spain, Italy, the Netherlands…) Google itself only shows a preview of about 400 characters and sends the reader to the job board, so that preview is what you get, together with the links to the full posting in `apply_options`.

**Is salary always available?** No — only when the listing shows pay. In test searches that was 20–30% of software engineering listings and 60–80% of nursing, trades and remote analyst listings; the rest have `salary: null`. `salary_currency` is read from the sign or code Google shows; a bare `$` is read as the dollar of the country you searched.

**How accurate is `posted_at`?** It is calculated from the age Google shows ("3 days ago") at the moment of the run, so it is accurate to the day, not the minute.

**Can I search in languages other than English?** Yes. Set **Language** to the country's own (`de`, `fr`, `es`, `it`, `pt`, `nl`, `ja`…). `posted_at` is filled in every language and `employment_types` in the eight languages named above. If you leave English on in a country that has no English-language listings (Italy, Japan, Portugal, Switzerland…), the Actor repeats the search in the local language by itself and tells you so in the log.

**My query returns nothing when I try it on Google Jobs. Will it work here?** Often, yes. Google Jobs shows no listings for a job title that is also something people look for nearby — `dentist chicago`, `physical therapist austin`, `zahnarzt berlin` — unless the search says it is about jobs. When a search comes back empty, the Actor repeats it once in its widest form: in the country's own language, without filter words, and with the word "jobs" (in English, German, French, Spanish, Italian, Portuguese, Dutch or Japanese). The log tells you exactly what was searched.

**What happens when Google does not answer a search?** Now and then Google stalls a search instead of answering it. The Actor recognises that, repeats the search, and in tests the repeat returned listings every time. If Google refuses twice, the query is reported as failed — not as "no results" — and it is not charged. The other queries of the run are unaffected.

**How long does a run take?** Most searches answer in about 20 seconds and all searches of a run are made in parallel, so a run takes about as long as its slowest search. A search Google stalls can take up to three minutes before it is repeated.

**Can I run it on a schedule or from my own code?** Yes. Use Apify schedules for recurring runs, or call the Actor through the Apify API, n8n, Make or Zapier. The output is flat JSON, ready for an MCP server or an LLM agent.

### More tools for hiring, leads and search data

- [Hiring Signals Finder](https://apify.com/santhej/hiring-signals-finder) — companies that are hiring for the roles you sell to, as sales leads.
- [Google Maps Scraper](https://apify.com/santhej/google-maps-scraper) — local businesses with phone, website, reviews and GPS.
- [Google News Scraper](https://apify.com/santhej/google-news-scraper) — every article on a company or topic, with publisher and publish time.
- [Google SERP API](https://apify.com/santhej/google-search-results-scraper) — organic results, People Also Ask and AI Overview for any query.

***

*Tags: google jobs scraper, google jobs api, jobs scraper, job listings api, job description scraper, job board data, salary data, apply links, remote jobs scraper, linkedin jobs, indeed jobs, recruiting data, hiring leads, labor market data, job search api*

# Actor input Schema

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

What to search on Google Jobs, for example 'software engineer new york' or 'registered nurse'. One search per line, up to 100 per run. Duplicates are removed.

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

A place added to every query, for example 'Austin, TX', 'London' or 'Bavaria'. Leave empty when your queries already name the place, or to search the whole country.

## `resultsDepth` (type: `integer`):

How many job listings to return for each query (10-200). You are charged per job actually returned.

## `locationCode` (type: `string`):

The country to search in. Every country in the list is one where Google Jobs is available.

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

Two-letter language code for the search, for example en, de, es, fr, ja. If a search finds nothing in this language, it is repeated once in the country's own language (Italy, Japan and Portugal, for example, have no English-language listings).

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

Only return jobs whose posting age falls within this window. Jobs that show no posting date are left out while a window is set. Removed jobs are not charged.

## `employmentType` (type: `array`):

Only return jobs whose listing shows one of these employment types. Leave empty for all types. Removed jobs are not charged.

## `workFromHome` (type: `boolean`):

Adds "remote" to each search so Google Jobs returns work-from-home / remote listings.

## `includeJobDetails` (type: `boolean`):

Adds the job description, qualifications, responsibilities, benefits, labels and every apply link to each row, at no extra charge. Turn it off for smaller rows.

## Actor input object example

```json
{
  "queries": [
    "software engineer new york"
  ],
  "resultsDepth": 20,
  "locationCode": "2840",
  "languageCode": "en",
  "datePosted": "all",
  "workFromHome": false,
  "includeJobDetails": true
}
```

# Actor output Schema

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

Every job listing found, one row each.

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

Queries searched, jobs returned, jobs removed by filters and the billing breakdown.

# 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 new york"
    ],
    "resultsDepth": 20,
    "locationCode": "2840",
    "languageCode": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("santhej/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 new york"],
    "resultsDepth": 20,
    "locationCode": "2840",
    "languageCode": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("santhej/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 new york"
  ],
  "resultsDepth": 20,
  "locationCode": "2840",
  "languageCode": "en"
}' |
apify call santhej/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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