# Google Jobs Scraper - Salary, Apply Links & Dates, No Login (`cliqtomedia/google-jobs-scraper`) Actor

Scrape Google Jobs listings for your job searches: title, company, location, salary, job type, posting date, full description and direct apply links. Pick the city and country; deep mode finds more jobs per search. No login.

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

## Pricing

from $0.85 / 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.
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 searches Google Jobs for your job titles and a location and returns one row per job: title, company, location, salary, job type, posting age, full description and the apply links to LinkedIn, Indeed or the employer site. It reads the public Google Jobs results page, so you need no Google login and no API key. The default input (`python developer` in Berlin, 10 jobs) usually takes 10–60 seconds and costs $0.033.

Use it for job market research, recruiting lead lists, salary checks and job feeds. The smallest run is one job title in the **Job searches** field.

![Google Jobs Scraper: a job search with location, date and job type gives job listings with company, salary and apply links on LinkedIn, Indeed or the employer site. 8 countries, up to 1,000 jobs per run, no login, no API key.](https://api.apify.com/v2/key-value-stores/v8WVjIHI3KucCaamC/records/README-BANNER-20261015.png)

### Table of contents

- [What it does](#what-it-does)
- [Quick start](#quick-start)
- [Use cases](#use-cases)
- [Input](#input)
- [Output](#output)
- [Pricing and limits](#pricing-and-limits)
- [API, export and integrations](#api-export-and-integrations)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Related Actors](#related-actors)
- [Support](#support)

### What it does

1. You add one or more job searches, for example `python developer` or `registered nurse`, and a location.
2. The Actor opens the [Google Jobs](https://www.google.com/search?udm=8\&q=jobs) results page for each search in the right Google country.
3. It reads every job card: title, company, location, the site Google found the job on (`via`), posting age, salary and job type.
4. It reads the job panel too: the full description, Google's highlights and all apply links, without tracking parameters.
5. It removes duplicate jobs (same Google job id) and saves one Dataset row per job.
6. **Fast** mode reads one Google page per search, about 10 jobs. **Deep** mode repeats each search with Google's date and job-type filters and removes duplicates, so you get several times more jobs.

#### Good fit

- Job market research: who hires for a role in a city, and on which job boards.
- Lead lists for recruiters and staffing agencies: companies with open roles, with the link to each job.
- Salary checks: Google's salary text where the job has one.
- A daily job feed for a niche job board, a Slack channel or a spreadsheet.

#### Not a fit / limits

- 8 countries only: United States, United Kingdom, Canada, India, Germany, France, Spain and Brazil (`countryCode`). Google shows the texts in the language of that country, for example `vor 1 Tag` and `Vollzeit` in Germany.
- Google shows about 10 jobs per search page. Fast mode gives about 10 jobs per search; deep mode about 20–70 (our tests). For more jobs, add more searches (up to 50) or more specific titles.
- `salary` is often `null`: Google shows a salary only for some jobs (0–40 % in our tests).
- `highlights` is often `null` in fast mode: Google does not send this block on many pages. The full `description` is still there.
- No recruiter names, emails or phone numbers. The Actor saves only the public job post.
- Google decides which jobs it shows. Two runs a few minutes apart can return a slightly different set or order.
- Google's terms do not allow automated access to Google Search. You are responsible for how you use the data.

### Quick start

1. Open the **Input** tab.
2. In **Job searches** (`queries`), keep `python developer` or add your own job title.
3. Keep **Location** `Berlin` and **Max jobs** `10`, or change them. **Country** `auto` picks the country from the location.
4. Click **Start**.
5. Open the **Output** tab. The **Jobs** table shows `title`, `company`, `location`, `salary` and the apply links.

Expected result: about 10 Python developer jobs in Berlin in Google's order, each with company, posting age and at least one apply link.

### Use cases

| Buyer job | Input path | Output entity | Key fields | Next integration |
| --- | --- | --- | --- | --- |
| Job market research | `queries` + `location`, `mode: "deep"` | Job | `title`, `company`, `via`, `postedAt` | CSV or Excel export |
| Recruiting lead list | `queries` like `"sales manager"` + `datePosted: "week"` | Job | `company`, `title`, `location`, `applyLinks` | Google Sheets or CRM through Apify integrations |
| Salary check | `queries` + `location` | Job | `salary`, `employmentType`, `title` | Spreadsheet |
| Daily job feed | `queries` + `datePosted: "today"` on a schedule | Job | `jobId`, `title`, `googleJobsUrl` | Slack, email or a website through webhooks |

### Input

#### Input fields

| Field | Plain name | Type | Required | Default / prefill | Allowed values | Effect | Example | Recommendation |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `queries` | Job searches | array of strings | yes | prefill `["python developer"]` | 1–50 searches | One Google Jobs search per item | `["data analyst", "nurse"]` | Use job titles people really write in job posts |
| `location` | Location | string | no | prefill `Berlin` | City, region or `remote` | Added to every search | `"Austin, TX"` | Leave empty to search the whole country |
| `countryCode` | Country | string | no | `auto` | `auto`, `us`, `gb`, `ca`, `in`, `de`, `fr`, `es`, `br` | Google country and language | `"gb"` | Keep `auto` when the location is a known city |
| `datePosted` | Date posted | string | no | `any` | `any`, `today`, `3days`, `week`, `month` | Only jobs posted in this period | `"week"` | Use `today` for a daily feed |
| `employmentType` | Job type | string | no | `any` | `any`, `fulltime`, `parttime`, `contractor`, `internship` | Only jobs of this type | `"fulltime"` | |
| `mode` | Search depth | string | no | `fast` | `fast`, `deep` | `deep` repeats each search with Google's filters | `"deep"` | Use `deep` when 10 jobs per search are not enough |
| `maxJobs` | Max jobs | integer | no | default `50`, prefill `10` | 1–1,000 | Stops the run at this many jobs in total | `200` | Keep the default 900-second timeout for more than 300 jobs |
| `includeDescription` | Include description | boolean | no | `true` | `true` / `false` | `false` leaves out `description` and `highlights` | `false` | Turn off for smaller rows; the price is the same |

Duplicate searches (same text, any case) run only once. A job that two searches find is saved once. If `queries` is empty, the run fails at once with `INVALID_INPUT` and makes no requests. A country outside the list above is rejected by the input form.

#### Interacting settings

| When | Input A | Input B | Effective behavior | Example | Cost/result effect |
| --- | --- | --- | --- | --- | --- |
| Empty location | `location: ""` | `countryCode` | The country name is added to the search, because Google Jobs needs a place | `"nurse"` → `nurse USA` | none |
| Country auto | `countryCode: "auto"` | `location` | Country from the location; unknown places use the United States | `"Lyon"` → France | none |
| Date or type filter | `datePosted`, `employmentType` | Google's results | Google's own filter, then jobs whose shown date or type does not match are dropped (`filteredOut` in `RUN_SUMMARY`). Jobs without a shown date or type are kept | `datePosted: "week"` | Dropped jobs are free; the page is still charged |
| Deep mode | `mode: "deep"` | `datePosted`, `employmentType` | Up to 9 Google pages per search: the base search, plus one per date filter if `datePosted` is `any`, plus one per job type if `employmentType` is `any`. With both filters set, deep mode is the same as fast | `mode: "deep"` | Up to 9 charged pages per search, several times more jobs |
| Job limit | `maxJobs` | `queries` | Searches run in order and stop at `maxJobs`; later searches may not run | `maxJobs: 10` with 3 searches | `RUN_SUMMARY.stopReason: "MAX_JOBS"` |

#### Input examples

##### Python jobs in Berlin (prefill)

```json
{
  "queries": ["python developer"],
  "location": "Berlin",
  "maxJobs": 10
}
```

Expected behavior: one Google Jobs page in Germany (`countryCode` auto → `de`).
Expected output: 10 job rows with `title`, `company`, `via`, `postedAt` and `applyLinks`.
Limit or cost note: $0.033 on the Free plan; about 10 seconds in our last test.

##### More jobs per search: deep mode in Houston

```json
{
  "queries": ["registered nurse", "pharmacist"],
  "location": "Houston, TX",
  "mode": "deep",
  "maxJobs": 100
}
```

Expected behavior: up to 9 Google pages per search (base, 4 date filters, 4 job types); duplicates removed. In our test these two searches found 60 and 59 jobs.
Expected output: 100 jobs with `searchVariant` showing which search found each job.
Limit or cost note: at most $0.34 on the Free plan (1 start, up to 18 pages, 100 jobs); usually a few minutes.

### Output

The Actor saves one row per job in the default Dataset. A search with no jobs gets one free `not_found` row, and a search that failed gets one free `error` row, so you always see what happened to each search. A run overview is saved as `RUN_SUMMARY` in the default Key-value store.

#### Output fields

| Field | Meaning | Type | Can be empty? | Example / enum | Source / notes |
| --- | --- | --- | --- | --- | --- |
| `status` | Row result | string | no | `complete`, `partial`, `not_found`, `error` | `partial` = deep search where some Google pages did not answer |
| `title` | Job title | string | yes | `Python Team Lead, Integration team` | As the employer wrote it |
| `company` | Employer | string | yes | `Fliff Inc` | |
| `location` | Job location as Google shows it | string | yes | `Berlin`, `Beliebiger Ort` (anywhere) | In the language of the country |
| `via` | Site Google found the job on | string | yes | `LinkedIn`, `Indeed` | |
| `postedAt` | Posting age as Google shows it | string | yes | `vor 1 Tag`, `2 days ago` | `null` when Google shows no date |
| `postedAtApprox` | Approximate posting date | string (YYYY-MM-DD) | yes | `2026-10-14` | `fetchedAt` minus `postedAt` |
| `salary` | Salary as Google shows it | string | yes | `65.000 € bis 85.000 € pro Jahr` | `null` = Google shows no salary (not zero) |
| `employmentType` | Job type as Google shows it | string | yes | `Full-time`, `Vollzeit` | |
| `workFromHome` | Remote job tag | boolean | yes | `true` | `null` when Google does not say |
| `description` | Full job description, plain text | string | yes | `We're looking for a Python Team Lead…` | `null` when `includeDescription` is off |
| `highlights` | Qualifications, Responsibilities, Benefits | array | yes | `[{"title": "Qualifications", "items": ["…"]}]` | Often `null` in fast mode |
| `applyLinks` | Where to apply | array | yes | `[{"title": "LinkedIn", "url": "https://…"}]` | Tracking parameters removed |
| `jobId` | Google's job id | string | yes | `eAHxzL0ATotpbjXSAAAAAA==` | Same job, same id across runs |
| `googleJobsUrl` | Google page that opens this job | string | yes | `https://www.google.de/search?ibp=htl;jobs&…` | |
| `position` | Order in this search after removing duplicates | integer | yes | `2` | `null` on `not_found` and `error` rows |
| `query`, `searchLocation`, `countryCode` | Your search, your location, the Google country | string | `searchLocation` yes | `python developer`, `Berlin`, `de` | |
| `searchVariant` | Which deep search found the job | string | yes | `datePosted:week` | `null` in fast mode |
| `source`, `sourceUrl` | Source name and the Google URL that was read | string | no | `google_jobs` | |
| `fetchedAt` | When the page was read, UTC | string (ISO 8601) | no | `2026-10-15T06:20:55.335Z` | |
| `statusReason`, `errorCode` | Why a row is not `complete` | string | yes | `SOURCE_TIMEOUT` | `null` on complete rows |

`null` means "Google shows no value"; it never means zero.

#### Output entities and surfaces

| Situation | Dataset/API/KVS/live view | Result shape | User action |
| --- | --- | --- | --- |
| Normal item | Dataset, view **Jobs** | `status: "complete"` job row | Use `title`, `company`, `applyLinks` |
| No jobs for a search | Dataset | one free `not_found` row with `statusReason` | Try a wider location or another title |
| Partial result | Dataset | `status: "partial"` rows of a deep search | Run again later for the missing pages |
| Technical failure | Dataset + `RUN_SUMMARY` | free `error` row with `errorCode`; run status `PARTIAL` or `ERROR` | Run again later; see Troubleshooting |
| Run overview | Key-value store record `RUN_SUMMARY` | status, stop reason, counts per search, charged pages and jobs | Check `status`, `stopReason` and `counts` |

#### Output example

```json
{
  "status": "complete",
  "title": "Python Team Lead, Integration team",
  "company": "Fliff Inc",
  "location": "Beliebiger Ort",
  "via": "LinkedIn",
  "postedAt": "vor 1 Tag",
  "postedAtApprox": "2026-10-14",
  "salary": null,
  "employmentType": "Vollzeit",
  "workFromHome": true,
  "description": "We’re looking for a Python Team Lead to join our Integration team, which owns a broad set of critical integrations across the product…",
  "highlights": null,
  "applyLinks": [
    { "title": "LinkedIn", "url": "https://de.linkedin.com/jobs/view/python-team-lead-integration-team-at-fliff-inc-4479228357" },
    { "title": "Startup Jobs", "url": "https://startup.jobs/python-team-lead-integration-team-fliff-inc-10437417" }
  ],
  "jobId": "eAHxzL0ATotpbjXSAAAAAA==",
  "googleJobsUrl": "https://www.google.de/search?ibp=htl;jobs&q=python+developer+Berlin&htidocid=eAHxzL0ATotpbjXSAAAAAA%3D%3D&hl=de-DE#…",
  "position": 2,
  "query": "python developer",
  "searchLocation": "Berlin",
  "countryCode": "de",
  "searchVariant": null,
  "source": "google_jobs",
  "sourceUrl": "https://www.google.de/search?q=python+developer+Berlin&udm=8&hl=de&gl=de",
  "fetchedAt": "2026-10-15T06:20:55.335Z",
  "statusReason": null,
  "errorCode": null
}
```

This is one row from the prefill run. The description, one apply link and the end of `googleJobsUrl` are shortened here. This job has no salary on Google, so `salary` is `null`.

#### Moving from another Google Jobs Actor

Field names are different from other Google Jobs Actors, so this Actor is not a drop-in replacement. Common changes: `company_name` → `company`, `share_link` → `googleJobsUrl`, `job_highlights` → `highlights`, `apply_options` → `applyLinks` (with `url` instead of `link`), `job_id` → `jobId` (Google's own id), `search_timestamp` → `fetchedAt`. Google's tag list (`extensions`) is split into `salary`, `employmentType`, `postedAt` and `workFromHome`.

### Pricing and limits

#### Pricing unit

This Actor uses pay-per-event pricing. You pay for:

| Event | When it is charged | Price |
| --- | --- | --- |
| Actor start (`apify-actor-start`) | Once per run (runs up to 1 GB memory) | $0.01 |
| Search page (`search-page`) | Each Google Jobs page that Google answered (up to 10 jobs), also a page with no jobs | $0.013 |
| Job (`job`) | Each unique job saved to the Dataset | $0.001 (Free plan), $0.00095 (Bronze), $0.0009 (Silver), $0.00085 (Gold and higher) |

Duplicates, jobs dropped by your date or type filter, `not_found` rows and `error` rows are free. Pages that failed are not charged, and a page that answers after `maxJobs` is reached is not charged. A search with no jobs costs one search page ($0.013). Apify platform usage (compute, proxy, storage) is included; you do not pay it separately.

If you set a maximum charge for the run, the Actor stops before it goes over it: `RUN_SUMMARY.status: "CAPPED"`, `stopReason: "CHARGE_LIMIT"`.

#### Cost examples

Prices on the Free plan, from our test runs.

| Scenario | Input scope | Pages | Jobs | Total |
| --- | --- | ---: | ---: | ---: |
| Prefill | 1 search, fast, 10 jobs | 1 | 10 | $0.033 |
| 100 jobs | 10 searches, fast | 10 | 100 | $0.24 |
| 1,000 jobs | 22 searches, deep | 196 | 1,000 | $3.56 |
| Nothing found | 1 search, no jobs | 1 | 0 | $0.023 |

Measured run times: 10 jobs in about 10–60 seconds (up to about 3 minutes when Google answers slowly), 100 jobs in about 2 minutes, 500 jobs in about 8 minutes, 1,000 jobs in about 8–9 minutes. Google answers each page in 4–20 seconds; more memory does not make it faster.

The default run timeout is 900 seconds. If a run reaches its timeout, the Actor stops by itself and keeps what it saved (`status: "CAPPED"`, `stopReason: "DEADLINE"`). For more than 300 jobs, keep the timeout at 600 seconds or more, or split the searches into several runs.

### API, export and integrations

- **API:** start the Actor with the [Apify API](https://docs.apify.com/api/v2) and read rows from the default Dataset (view `jobs`).
- **Export:** download the Dataset as JSON, CSV, Excel, XML or HTML from the **Output** tab.
- **Scheduling:** create a [schedule](https://docs.apify.com/platform/schedules) with `datePosted: "today"` for a daily job feed. Use `jobId` to skip jobs you already have.
- **Webhooks / no-code:** send new rows to Slack, Google Sheets, Make, Zapier or n8n through [Apify integrations](https://docs.apify.com/platform/integrations).

#### Use with AI agents (MCP)

- MCP server with only this Actor: `https://mcp.apify.com?tools=cliqtomedia/google-jobs-scraper`.
- Smallest useful input:

```json
{ "queries": ["python developer"], "location": "Berlin", "maxJobs": 10 }
```

- Key output fields: `title` (job title), `company` (employer), `location`, `salary` (text or `null`), `applyLinks` (where to apply), `status` (`complete`, `partial`, `not_found` or `error`).
- A 10-job run usually takes 10–60 seconds and costs $0.033 on the Free plan. Keep `maxJobs` small (10–50) and `mode: "fast"` for agent calls; 1,000 jobs take about 8 minutes.

### Troubleshooting

#### The run failed at once

Symptom: run status FAILED in a few seconds, no rows.
Likely reason: invalid input (`INVALID_INPUT`), for example no searches.
Check: the run log and `RUN_SUMMARY.message`.
Action: fix the input and start again.

#### A search returned one not_found row

Symptom: one row with `status: "not_found"`.
Likely reason: Google Jobs has no jobs for this search, place and filter.
Check: `statusReason` and `sourceUrl`; open `sourceUrl` in a browser.
Action: try a more common job title, a bigger city, or `datePosted: "any"`.

#### Error rows with SOURCE_TIMEOUT or SOURCE_BLOCKED

Symptom: free `error` rows with `errorCode` `SOURCE_TIMEOUT`, `SOURCE_UNAVAILABLE` or `SOURCE_BLOCKED`.
Likely reason: Google did not answer in 60 seconds after retries, or refused the request.
Check: `RUN_SUMMARY.http` (requests, retries, timeouts, blocked).
Action: run these searches again later. The Actor does not solve CAPTCHAs.

#### The run stopped with CAPPED and DEADLINE

Symptom: `RUN_SUMMARY.status: "CAPPED"`, `stopReason: "DEADLINE"`, fewer jobs than `maxJobs`.
Likely reason: the run timeout was too short for the number of jobs.
Check: the run timeout in the run options.
Action: keep the default 900 seconds, or split the searches into several runs. Searches that did not start get free `error` rows.

#### Fewer jobs than maxJobs

Symptom: the run is `COMPLETE` with fewer jobs than you asked for.
Likely reason: in fast mode Google shows about 10 jobs per search; filters drop jobs that do not match.
Check: `RUN_SUMMARY.counts` (`jobs`, `duplicates`, `filteredOut`).
Action: use `mode: "deep"` or add more searches.

### FAQ

#### Do I need a Google account or API key?

No. The Actor reads the public Google Jobs results page without login, cookies or keys.

#### Is this the official Google Jobs API?

No. Google has no public API for Google Jobs search results. This Actor is not made by or linked to Google.

#### Why are some texts in German or French?

Google shows jobs in the language of the country you search. Search in Germany, and `postedAt` says `vor 2 Tagen` and `employmentType` says `Vollzeit`. `postedAtApprox` gives a date that is the same in every language.

#### Why is salary empty for most jobs?

Google shows a salary only when the job post or job board gives one. The Actor does not guess: no salary on Google means `salary: null`.

#### Can I get the recruiter's email or phone?

No. The Actor saves only the public job post and does not collect personal contact data.

### Related Actors

- [Remote Jobs Aggregator](https://apify.com/cliqtomedia/remote-jobs-aggregator) — remote jobs from RemoteOK, We Work Remotely and Himalayas.
- [Greenhouse Jobs Scraper & Monitor](https://apify.com/cliqtomedia/greenhouse-jobs-monitor-scraper) — all jobs of a company that you found on Google, straight from its Greenhouse job board.
- [Lever Job Scraper](https://apify.com/cliqtomedia/lever-jobs-scraper) — the same for companies on Lever.

### Support

For bugs, questions or feature requests, open an issue on the **Issues** tab of this Actor. Include the run ID, your input and the error text. Never send tokens, cookies or private data.

# Changelog

This Actor's version history is a separate document: https://apify.com/cliqtomedia/google-jobs-scraper/changelog.md

# Actor input Schema

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

What to search on Google Jobs, one per line, e.g. "python developer" or "registered nurse". Up to 50 searches; duplicates are removed.

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

City, region or "remote", added to every search, e.g. "Berlin", "Austin, TX" or "London". Leave empty to search the whole country: Google Jobs needs a place, so the country name is added ("nurse" → "nurse USA").

## `countryCode` (type: `string`):

Google country and language to search in. Auto picks it from the location ("Berlin" → Germany, "Austin, TX" → United States); unknown places use the United States.

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

Only jobs posted in this period. Uses Google's own date filter, then drops jobs whose shown posting date is older (they are not written or charged).

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

Only jobs of this type. Uses Google's own job-type filter, then drops jobs whose shown job type is a different one (not written or charged).

## `mode` (type: `string`):

Google Jobs shows about 10 jobs per search. Deep mode repeats each search with Google's date and job-type filters and removes duplicates, so you get several times more jobs.

## `maxJobs` (type: `integer`):

Stop after this many jobs in total for the run. You pay only for jobs written to the Dataset.

## `includeDescription` (type: `boolean`):

Add the full job description and Google's highlights (qualifications, responsibilities, benefits). Turn off for smaller rows.

## Actor input object example

```json
{
  "queries": [
    "python developer"
  ],
  "location": "Berlin",
  "countryCode": "auto",
  "datePosted": "any",
  "employmentType": "any",
  "mode": "fast",
  "maxJobs": 10,
  "includeDescription": true
}
```

# Actor output Schema

## `jobs` (type: `string`):

Jobs as a table.

## `runSummary` (type: `string`):

Status, per-search counts, charged events and request statistics.

# 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"
    ],
    "location": "Berlin",
    "maxJobs": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("cliqtomedia/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"],
    "location": "Berlin",
    "maxJobs": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("cliqtomedia/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"
  ],
  "location": "Berlin",
  "maxJobs": 10
}' |
apify call cliqtomedia/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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