# Google Jobs Scraper: Job Listings by Keyword and Place (`quarra/google-jobs-scraper`) Actor

Google Jobs listings by keyword, place and country: title, company, location, remote or on-site, employment type, salary read into min, max, currency and period, posting date, apply link and source. Filters by age and type. Many searches per run.

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

## Pricing

from $3.60 / 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: Job Listings, Salary, Employer, Source & Apply Link

Search Google Jobs the way a candidate does and get the listings as data: title, employer, place, contract type, the salary
when the listing shows one, the date it was posted, the site that lists the job and the link to apply. Run many searches in
one go, by country, language and place, with the duplicates removed. Built for job boards and aggregators, recruiters,
salary and hiring-trend research, and lead lists of companies that are hiring.

**$3.90 per 1,000 jobs** (one job = one listing delivered), **$0.003 per search** answered by Google Jobs (one fee per 20 jobs
read, empty search included) and a small start fee per run. A run of 30 jobs from 2 searches costs about $0.13.

### Quick start

1. Type your **searches**, one per line (`python developer`, `nurse`, `warehouse operator`).
2. Pick the **country** and, if you want, the **language** and one or more **places** (`Lyon`, `Texas`, `SW1A 1AA`).
3. Set the **maximum jobs**, click **Start** and read the jobs in the **Output** tab.

It also runs from the Apify API, on a schedule, and connects to webhooks, Make, Zapier, n8n or Apify's MCP server. Run
the same searches every day to follow the market.

### What it is used for

- **Job boards and aggregators**: fresh listings by country, place and keyword.
- **Salary and market research**: the pay that listings show, by job and place, with the figures read out for you.
- **Hiring signals**: which companies are hiring for what, and where.
- **Alerts**: a daily schedule with "posted within 1 day" gives the new listings that Google dates (about 6 in 10 are dated;
  the undated ones are left out).

### What you get

| | |
|---|---|
| Title, employer, place | yes |
| Contract type | read from Google's text: full-time, part-time, contract, internship, temporary |
| Salary as written, plus minimum, maximum, currency and period | when the listing shows one; figures left empty when they cannot be read with certainty |
| Date posted | when Google shows one |
| Site that lists the job, and the link to the listing | yes |
| Remote | `remote` when Google lists the job as "Anywhere" |
| The search and place that found it, position in Google's list, time read | yes |

### Inputs

- **Searches**: up to 500 per run, repeats are searched once. A job found by several searches is delivered once.
- **Places** (optional): a city, region or postal code per line. Each search runs in each place. Leave empty to search the
  whole country. If a name is shared by several places, write the region (`Springfield, Missouri`): the run says which
  places matched, for free.
- **Country**: the 76 countries where Google Jobs is available. **Language**: a code (`en`, `fr`, `de`, `pt-BR`...);
  empty uses the main language of the country.
- **Maximum jobs** and **maximum jobs per search** (up to 200). Apify's **Maximum cost per run** is respected too.
  When you give more searches than the maximum can serve, every search gets a share (at least 5 jobs) and the first
  ones are served first; a search that finds fewer jobs than its share gives the rest to the others.
- **Posted within** (last 1, 3, 7, 14 or 30 days), **contract types** and **radius** (1 to 300 km around each place).

### Output

One record per job. Main fields: `jobId`, `title`, `company`, `location`, `workplaceType`, `employmentType`,
`employmentTypeRaw`, `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `publishedAt`, `postedAgo`,
`source`, `url`, `query`, `searchLocation`, `rank`, `scrapedAt`. A search that gives nothing comes as an `error` record (the record is free; the search fee applies only if Google Jobs answered the search)
with the reason and whether trying again may help. The run summary (OUTPUT) gives the jobs per search and how many jobs
the filters left out.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| Job delivered | $3.90 per 1,000 |
| Search | $0.003 per search, per 20 jobs read (a search read 50 deep counts 3) |
| Run start | $0.005 per run |

The search fee is charged once the search is accepted by the job data service, whether Google shows jobs or not: a search
with no listing costs $0.003 and gives a free record saying so, the other searches carry on. It is never charged when the
service is down or refuses the search, and a search is not sent when your maximum cost per run no longer leaves room for
its fee and at least one job. A run starts with at most 3 searches of 20 jobs and sends the rest once Google Jobs has
answered; if Google Jobs keeps failing, the run stops after at most 3 to 5 search fees. Higher Apify plans pay less per job ($3.70 and $3.60 per 1,000 on the upper plans). Never
charged: error records, jobs already delivered by another search, notices. **The search fee is counted per block of 20 jobs read, including the jobs a tight filter drops**: with a "posted within" or contract filter the
Actor reads deeper to find enough matching jobs (up to 6 times the jobs you asked for), and the fee counts everything it read.
When a search has fewer jobs than its share, the others are read deeper to fill your maximum: Google is asked again from the
top, and only the new blocks of 20 are charged (a search read 20 deep, then 60 deep, pays 3 fees in all).

### Limits

- **Google shows about 190 jobs at most per search.** Use more searches and places to go further.
- **Not every field exists for every job.** The salary is only there when the listing shows it, the date for about 6 jobs in
  10, the employer website rarely. Missing values are empty, never made up.
- **Dates have a day's precision.** Google says "3 days ago", so `publishedAt` is that day (`YYYY-MM-DD`).
- **Remote** is set only when Google lists the job as "Anywhere"; on-site and hybrid are not told apart.
- **One link per job**: the listing on the site Google shows first. The description is not included.
- **Contract filter**: read from the contract text in the search language; jobs showing no contract are left out when you filter,
  and so are jobs whose contract text cannot be read (the run summary says how many).
- **Short "posted within" windows return fewer jobs**: Google dates only about 6 jobs in 10 and the Actor reads deeper to find the recent ones, within the cost limit of the run. For the most jobs, widen the window or add searches and places.
- Results are what Google shows at that moment and change from one hour to the next.

### FAQ

**Is anything different on Apify's free plan?** Live searches need a paid Apify plan. On the free plan, the prefilled
example (the search "python developer", United States, 20 jobs) returns a stored sample, marked `sample: true` with its date.
Any other input searches nothing and says so in the run. Only the run start is charged.

**What if a run is restarted by the platform?** It resumes where it was: jobs already delivered are not searched or charged again.

**Does the Actor send anything to Quarra?** Only when a run fails or runs out of time: the Actor, its build, the error type, the line of our code where it happened, and the memory and time the run was given, so we can fix it fast. Never your searches, your results, your account or the run ID.

# Actor input Schema

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

One job title, skill or keyword per line (python developer, nurse, warehouse operator). C++ and 100% work as written. Search operators such as site: are not supported. The same job found by several searches is delivered once.

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

One city, region or postal code per line (Lyon, Texas, SW1A 1AA). Leave empty to search the whole country. Write the region when a name is shared by several places ('Springfield, Missouri'): an ambiguous place is refused with a free record that lists the choices.

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

Google Jobs country. The 76 countries where Google Jobs is available are listed; others are not served by Google.

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

Language of the results: a code such as en, fr, de, es, pt-BR. Empty = the main language of the country. Contract and salary texts, and 'posted 3 days ago', come in this language.

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

Stop after this many jobs in total, shared between your searches. Leave empty for no limit other than your maximum charge per run.

## `maxItemsPerSearch` (type: `integer`):

Most jobs delivered for one search (one search in one place). Google lists about 190 jobs at most per search: use several searches and places to go further.

## `maxAgeDays` (type: `string`):

Keep jobs posted within this time. Google dates a job with a day count ('3 days ago'), so the limit is to the day. About 4 jobs in 10 show no date; see the next option.

## `keepUndated` (type: `boolean`):

With a 'Posted within' filter, also keep jobs that show no date. Off: they are left out (their date cannot be checked).

## `employmentTypes` (type: `array`):

Keep only these contract types. Read from the contract text Google shows; jobs that show no contract type are left out when you pick one.

## `radiusKm` (type: `integer`):

Search this far around each place (1 to 300 km). Empty = Google's default for the place. Only with a place.

## Actor input object example

```json
{
  "queries": [
    "python developer"
  ],
  "country": "US",
  "maxItems": 20,
  "maxItemsPerSearch": 50,
  "maxAgeDays": "any",
  "keepUndated": false
}
```

# Actor output Schema

## `results` (type: `string`):

Every job, and free rows with the reason when a search found nothing.

## `overview` (type: `string`):

One line per job: title, employer, place, contract, salary, date, source.

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

Counts per search, filtered-out jobs, why the run stopped.

# 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": [
        "python developer"
    ],
    "country": "US",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("quarra/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": ["python developer"],
    "country": "US",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("quarra/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": [
    "python developer"
  ],
  "country": "US",
  "maxItems": 20
}' |
apify call quarra/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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