# Google Jobs Scraper — Descriptions, Salaries, Apply Links (`architekture/google-jobs-scraper`) Actor

Google Jobs scraper for US job searches: title, company, location, salary, posting age, employment type, full description, job highlights and every apply link. Query expansion runs 7 searches per query and keeps unique jobs only; watch mode delivers only new jobs. Pay per result, no login.

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

## Pricing

$3.50 / 1,000 delivered jobs

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

## Google Jobs Scraper — Descriptions, Salaries, Apply Links

**Recorded run: 100 jobs from 10 searches in 91 seconds** (2026-10-24, build 0.1.1, run `IUbu3u7h1OveEIjrf`; 10 US role-and-city searches, 100 `job` charges, 0 blocked). A bounded canary sample, not a full-catalogue benchmark. At $3.50 per 1,000 jobs this costs less than half of the most-used Google Jobs actor in the Store (about $9 per 1,000 jobs at $0.09 per page of about 10 jobs on its free tier), and every one of the 9 validation runs on 2026-10-24 succeeded and charged exactly the jobs it delivered.

architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.

**What's new**

- **2026-10-25** — Five input recipes, a head-to-head table, n8n and Make imports and MCP setup for Claude and Cursor added to this page; output and prices unchanged.
- **2026-10-24** — First version: Google Jobs search in the US with full descriptions, job highlights and direct apply links; `expandQueries` for up to 7 searches per query with jobs deduplicated by `jobId`; hiring watch mode; resumable runs.

Google Jobs search results as JSON: give it job searches such as "nurse jobs near Chicago, IL" and get every job Google shows, each with title, company, location, source, posting age, employment type, salary when published, the full description, Google's job highlights and every apply link.

| Source | Market | From | Standout fields |
|---|---|---|---|
| Google Jobs (the Jobs tab of google.com search) | United States | $3.50 / 1,000 jobs | `description`, `applyOptions[].url`, `salaryText`, `highlights` |

### ✅ Why choose this scraper

- **The full posting in every row, no second request.** `description` (line breaks kept), `highlights.qualifications` / `benefits` / `responsibilities` and `applyOptions` come from the same search page as the title, so one $0.0035 row is the complete job. In run `IUbu3u7h1OveEIjrf` 100 of 100 jobs had a description over 200 characters and at least one direct apply link (5.5 per job on average, up to 8).
- **Direct apply links.** `applyOptions[].url` is the job board's or employer's own posting URL (LinkedIn, Indeed, Workday, company career sites), not a Google redirect, with the button label in `title` and the site in `domain`.
- **More than Google's 10 jobs per search, without paying twice.** `expandQueries` runs 7 searches per query (the query plus 6 refinements) and delivers each job once, deduplicated by `jobId` across searches and queries. Run `AliOdsNDVWAqyR3hk`: "registered nurse jobs near Houston, TX" expanded to 7 searches gave 53 unique jobs; the 13 repeats were free.
- **Charges equal delivered rows, measured.** 9 validation runs on build 0.1.1 delivered 280 jobs and recorded 280 `job` charges; 0 runs failed. Status rows, searches with no jobs, repeated jobs and unchanged watch rows were free.
- **Hiring watch that charges only for new jobs.** With `incrementalMode` and a `stateKey`, later runs deliver only jobs not delivered before for that key. The watch rerun `b28aKFY0ZSIj4I11o` charged the 5 jobs Google had added and skipped the 15 it had already delivered, for free.

#### Tested head-to-head (2026-10-25)

| | This actor | The field (16 job actors in the store search) |
|---|---|---|
| Runs that did not succeed | 0 of 6 recorded canary runs (2026-10-24 to 2026-10-25) | median 5.5%, range 0–100%; 10 of 16 had failed runs (30-day store stats) |
| Rows per run | 12.2 jobs per canary run (2 searches daily; a watch run delivers only new jobs) | not published |
| Price | $3.50 / 1,000 jobs | median $5.50 / 1,000, range $0.80–$200.00 |

### ⚠️ Worth knowing up front

- **Google shows about 10 jobs per search to this route, and there is no page 2.** Google loads more jobs in the browser through a session-bound request that a server route cannot make; `start=` and `num=` return nothing new (tested 2026-10-24). For more coverage use `expandQueries`, more specific searches (a neighbouring town, a seniority, a company name), or both.
- `expandQueries` adds exactly these 6 searches per query: `<query> in the last 3 days`, `<query> remote`, `senior <query>`, `entry level <query>`, `<query> full time`, `<query> contract`. Some refinements return few or no jobs for some queries; each search with no jobs is a free `NO_RESULTS` row. Recorded unique jobs per expanded query: 57 (software engineer, Austin, Phase 0) and 53 (registered nurse, Houston, run `AliOdsNDVWAqyR3hk`).
- `postedText` is Google's relative text ("3 days ago"); Google shows no posting date. `salaryText` appears only when the employer published a salary (44 of 100 jobs in run `IUbu3u7h1OveEIjrf`). `postedText` was missing on 26 of those 100 jobs and `employmentType` on 1.
- Apply links are the ones Google lists for the job. Google groups near-identical postings, so a button can lead to the same role posted on another site or for another office.
- US jobs only in this version: searches run on google.com with `gl=us` and `hl=en` through a US proxy. A page in another language or with mostly non-US jobs is fetched again (3 attempts), then becomes a free `SOURCE_ERROR` row, so a search for jobs outside the US returns nothing.
- Pacing: Google pages take about 2 to 60 seconds through the SERP proxy (median about 8 seconds in Phase 0), two searches at a time, so plan about 5 to 10 searches per minute. Measured on 2026-10-24: 10 searches in 91 seconds, one query expanded to 7 searches in 141 seconds. Each page is fetched with a 90-second timeout and retried once.
- A run stops cleanly 3 minutes before its deadline (`PARTIAL`, `stopReason` `ACTOR_DEADLINE`), at your spending limit (`BUDGET_LIMIT`), and after two blocked searches in a row (`PARTIAL`). The deadline is the run timeout, capped at 6 hours. Rerun with the same `stateKey` to continue.
- Invalid input (`INVALID_INPUT`), a `stateKey` still held by another run (`STATE_BUSY`), a search with no jobs (`NO_RESULTS`), a blocked, failed or other-market page (`BLOCKED`, `SOURCE_ERROR`, `SOURCE_CHANGED`), the deadline (`ACTOR_DEADLINE`) and the spending limit (`BUDGET_LIMIT`) each write a free status row (`"recordType": "status"`). An unconfirmed delivery (`RECONCILIATION_REQUIRED`) or a storage fault fails the run and replays nothing.

### ⚡ Try the example

This actor has no free preview of its own; the example below costs about $0.035 (one search, up to 10 jobs).

Open the actor's input page, switch to JSON, paste this and start the run:

```json
{
  "queries": ["software engineer jobs near Austin, TX"]
}
```

Add more searches to `queries` (up to 50), and set `"expandQueries": true` for up to 7 searches per query.

### ⚙️ Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `queries` | array | — (prefill `["software engineer jobs near Austin, TX"]`) | 1–50 Google Jobs searches, as typed into Google: a role and a place ("nurse jobs near Chicago, IL"), a remote search ("remote data analyst jobs") or a company ("Tesla jobs near Austin, TX"). Duplicates are removed. |
| `expandQueries` | boolean | `false` | Also run the 6 refinements listed above for each query. Jobs found by several searches are delivered and charged once. |
| `incrementalMode` | boolean | `false` | Needs `stateKey`. Deliver and charge only jobs (by `jobId`) not delivered before for this key. |
| `stateKey` | string | — | Any name up to 100 characters. Keeps the watch baseline and lets an interrupted run resume. One key per set of inputs. |
| `feedback` | string | — | Optional note for the maintainers. It is logged and read by a human, and it never changes output. |

The run's spending limit (`maxTotalChargeUsd`, set in the run options) caps how many jobs are delivered.

#### Input recipes

Linked recipes open a public example task with exactly this input; run it as is or copy it. Paste the others into the JSON tab of the input page.

- [One search, about 10 jobs](https://apify.com/architekture/google-jobs-scraper/examples/gjobs-us-software-austin): `{"queries": ["software engineer jobs near Austin, TX"]}`
- [One query expanded to 7 searches, unique jobs only](https://apify.com/architekture/google-jobs-scraper/examples/gjobs-us-nurse-expanded): `{"queries": ["nurse jobs near Chicago, IL"], "expandQueries": true}`
- [Hiring watch: only new jobs for 3 searches](https://apify.com/architekture/google-jobs-scraper/examples/gjobs-us-hiring-watch): `{"queries": ["data analyst jobs near New York, NY", "electrician jobs near Phoenix, AZ", "remote product manager jobs"], "incrementalMode": true, "stateKey": "us-hiring-watch"}`
- Remote roles across the US: `{"queries": ["remote data engineer jobs"], "expandQueries": true}`
- Several cities for one role in one run: `{"queries": ["registered nurse jobs near Houston, TX", "registered nurse jobs near Phoenix, AZ", "registered nurse jobs near Atlanta, GA"]}`

### 🧱 Stable fields

These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.

| Field | Type | Meaning |
|---|---|---|
| `query` | string | Your query as given (whitespace collapsed). |
| `searchQuery` | string | The text sent to Google: the same as `query`, or one of its `expandQueries` refinements. |
| `country` | string | `us`. |
| `position` | number | Rank of the job on its Google search page (1 = first). |
| `jobId` | string | Google's job id. The same job found by two searches has the same `jobId`; it is the dedupe and watch key. |
| `title` | string | Job title. |
| `company` | string, nullable | Employer name. |
| `location` | string, nullable | Google's location text, for example `Austin, TX`, `Anywhere` or `Austin, TX (+2 others)`. |
| `via` | string, nullable | The source Google names, for example `LinkedIn`, `Indeed` or `Schwab Jobs`. |
| `postedText` | string, nullable | Google's relative posting age, for example `2 days ago`. |
| `employmentType` | string, nullable | For example `Full-time`, `Contractor`, `Full-time, Part-time, and Contractor`. |
| `salaryText` | string, nullable | The salary as shown, for example `$164K–$205K a year` or `$50 an hour`; `null` when the employer published none. |
| `workFromHome` | boolean | `true` when Google tags the job "Work from home". |
| `chips` | array | Every label on the job card, for example `Posted 2 days ago`, `Employment Type Full-time`, `Qualification No degree mentioned`. |
| `description` | string, nullable | The full job description, with line breaks. |
| `highlights` | object | Google's "Job highlights": `qualifications`, `benefits` and `responsibilities`, each a list of strings (empty when Google shows none). |
| `applyOptions` | array | One object per apply button: `title` (for example `Apply on LinkedIn`), `url` (the posting on that site) and `domain`. |
| `shareUrl` | string, nullable | Google's share link for the job. |
| `scrapedAt` | string | Collection time, UTC ISO 8601. |
| `recordType` | string | `"status"` on free status rows; `"job"` on data rows. |

Data rows also carry `deliveryId` (unique per delivered row). Status rows carry `recordType`, `inputRef` (the search text), `status` and `message`. Other fields are extras, not part of the contract. To have one pinned, say so in `feedback`.

### 📦 Output example

Abridged real row from run `IUbu3u7h1OveEIjrf` on 2026-10-24 (description cut, one item per highlight list, 2 of 8 apply options, `shareUrl` shortened); values are a historical snapshot.

```json
{
  "recordType": "job",
  "query": "software engineer jobs near Austin, TX",
  "searchQuery": "software engineer jobs near Austin, TX",
  "country": "us",
  "position": 3,
  "jobId": "ZrBruAaEW4Eb97eJAAAAAA==",
  "title": "Sr Software Engineer",
  "company": "Charles Schwab",
  "location": "Austin, TX (+2 others)",
  "via": "Schwab Jobs",
  "postedText": "12 days ago",
  "employmentType": "Full-time",
  "salaryText": "$164K–$205K a year",
  "workFromHome": false,
  "chips": [
    "Posted 12 days ago",
    "Salary $164K–$205K a year",
    "Employment Type Full-time",
    "Qualification No degree mentioned"
  ],
  "description": "Your opportunity\n\nAt Schwab, you’re empowered to make an impact on your career. Here, innovative thought meets creative problem solving, ...",
  "highlights": {
    "qualifications": [
      "8+ years of software engineering experience"
    ],
    "benefits": [
      "In addition to the salary range, this role is also eligible for bonus or incentive opportunities"
    ],
    "responsibilities": [
      "The engineer will work closely with architects, product teams, infrastructure partners, and business stakeholders to transform ideas into working prototypes and production-ready solutions"
    ]
  },
  "applyOptions": [
    {
      "title": "Apply on Schwab Jobs",
      "url": "https://www.schwabjobs.com/job/austin/sr-software-engineer/33727/101909398560?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
      "domain": "schwabjobs.com"
    },
    {
      "title": "Apply on CareerBuilder",
      "url": "https://www.careerbuilder.com/job-details/sr-software-engineer-blockchain-ann-arbor-mi--34192420-ab6d-446d-b589-b215d70fe39c?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
      "domain": "careerbuilder.com"
    }
  ],
  "shareUrl": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer+jobs+near+Austin,+TX&htidocid=ZrBruAaEW4Eb97eJAAAAAA%3D%3D&hl=en-US...",
  "scrapedAt": "2026-10-24T21:33:21.717697+00:00",
  "deliveryId": "2768132ebb1bd912996312d73ff94090-2"
}
```

A free status row looks like this (run `F4p8zrCPSt9ND01DA`, a nonsense search):

```json
{"recordType": "status", "inputRef": "zqxjvbwkpfh qwmzrtvxl jobs", "status": "NO_RESULTS", "message": "Google Jobs shows no jobs for this search; nothing was charged"}
```

The run's status message reads `Done: N rows, 0 details, K status rows (STATUS)`, and the `RUN_SUMMARY` record of its key-value store holds the outcome (abridged, the expanded run `AliOdsNDVWAqyR3hk`):

```json
{"status": "COMPLETE", "delivered": 53, "charged": {"job": 53}, "chargeUsd": "0.1855", "statusRows": 0, "duplicates": 13, "queriesFetched": 7, "serpRequests": 7, "checkpointComplete": true}
```

### 🧠 Advanced usage

**Daily hiring watch.** Schedule a run with your searches, `"incrementalMode": true` and `"stateKey": "us-hiring-watch"`. The first run delivers every job; later runs deliver (and charge) only jobs whose `jobId` was not delivered before under that key, so the dataset of each run is the list of new postings. Google reorders and refreshes its 10 jobs per search between days, which is where new jobs appear.

**Wider coverage for one role.** Use `"expandQueries": true` and add neighbouring places as separate queries ("nurse jobs near Evanston, IL", "nurse jobs near Oak Park, IL"). Every job is delivered once across all of them; `searchQuery` tells you which search found it.

**Route by apply site.** `applyOptions[].domain` names each site that carries the posting (for example `linkedin.com`, `myworkdayjobs.com`, the employer's career site). Filter on it to keep employer-direct postings or to send each job to the board you use.

**Resume an interrupted collection.** With a `stateKey`, a run that stops at the deadline, the spending limit or a forced stop keeps its progress; start the same input again with the same key. Jobs already delivered are not delivered or charged again. After a forced stop, the key is free again once the stopped run's timeout plus 60 seconds has passed (`STATE_BUSY` before that).

### 🔌 Integrations

Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. A daily run with `incrementalMode` turns a list of searches into a feed of new job postings. Copy-paste code in Python, Node, curl and n8n: [architek-earth/examples/google-jobs-scraper](https://github.com/architek-earth/examples/tree/main/google-jobs-scraper).

#### n8n and Make

- n8n: import [n8n-workflow.json](https://github.com/architek-earth/examples/blob/main/google-jobs-scraper/n8n-workflow.json) (runs the actor with the example input and returns the dataset rows).
- Make: import [make-blueprint.json](https://github.com/architek-earth/examples/blob/main/google-jobs-scraper/make-blueprint.json) (the same run as a Make scenario).

### 💸 Pricing

Pay per result. Platform and proxy usage are included. Status rows and failed requests are free. Each job is charged once, after it is written to the dataset; a job found again by another search in the same run, or (in watch mode) by an earlier run with the same `stateKey`, is not delivered or charged again, and a resumed run continues after the last confirmed batch without re-charging it (a batch whose charge was left unconfirmed by a crash is counted in `RUN_SUMMARY.recoveredUncertainCharges` and not charged again).

| Event | Price | What it covers |
|---|---|---|
| `job` | $3.50 / 1,000 jobs | One delivered job row with its description, highlights and apply links. |

1,000 jobs cost $3.50; one search of 10 jobs costs $0.035; one query expanded to 7 searches cost $0.19 for 53 unique jobs in run `AliOdsNDVWAqyR3hk`. The Apify free plan's $5 monthly credit covers about 1,428 jobs at $3.50 / 1,000.

### ❓ FAQ

**Is there a Google Jobs API?** Google does not offer a public one. This actor works as one: it returns Google Jobs search results as JSON through the Apify API, callable from any language or from n8n, Make and Zapier.

**Do I need a Google account, cookies or my own proxy?** No. Requests go through Apify's Google SERP proxy in the US; no login, cookies or Google API key.

**Why do I get at most about 10 jobs per search?** That is what Google renders for a search on this route; the rest of its list loads in the browser through a session-bound request. `expandQueries` and more specific searches are the way to more jobs.

**Are the apply links Google redirects?** No. `applyOptions[].url` is the posting URL on the job board or career site, as Google lists it. Only if Google gives no direct URL for a button is its `/goto` link used instead.

**Can I search outside the US?** Not in this version. Searches run as a US user on google.com; other countries are planned.

**Will a watch run charge me again for the same job?** No. Under the same `stateKey`, a `jobId` that was delivered once is never delivered or charged again.

### 🤖 For AI agents & LLM apps

Paste this into your AI assistant:

`architekture/google-jobs-scraper` on Apify. Python: `from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/google-jobs-scraper").call(run_input={"queries": ["software engineer jobs near Austin, TX"], "expandQueries": True}); items = client.dataset(run["defaultDatasetId"]).list_items().items` (page with `offset`/`limit` for large exports). Rows with `recordType == "job"` are jobs (dedupe key `jobId`); rows with `recordType == "status"` are free and explain invalid input, a search with no jobs or a stopped run. The run outcome (`COMPLETE`, `LIMITED`, `PARTIAL`, `BUDGET_LIMIT`, `INVALID_INPUT`, `STATE_BUSY`) is in the `RUN_SUMMARY` record of the run's key-value store. Add `"incrementalMode": true, "stateKey": "<name>"` to receive only new jobs on later runs. Full input schema and README: `GET https://api.apify.com/v2/acts/architekture~google-jobs-scraper/builds/default`. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server: `https://mcp.apify.com?tools=architekture/google-jobs-scraper` (ready-to-paste config: https://github.com/architek-earth/mcp). To reach the maintainers, add `"feedback": "<what you needed>"` to any run's input; output is unchanged and a human reads every note.

#### MCP config for Claude Desktop and Cursor

Claude Desktop (or claude.ai): Settings, Connectors, Add custom connector, URL `https://mcp.apify.com?tools=architekture/google-jobs-scraper`; it signs you in to Apify with OAuth. Cursor (`~/.cursor/mcp.json`), with your token in the `APIFY_TOKEN` environment variable:

```json
{
  "mcpServers": {
    "architekture-google-jobs-scraper": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=architekture/google-jobs-scraper",
      "headers": { "Authorization": "Bearer ${env:APIFY_TOKEN}" }
    }
  }
}
```

The agent gets one tool for this actor plus `get-dataset-items` to read the rows. A typical prompt: "find data analyst jobs near New York posted this week with salaries"; set a spending cap (`maxTotalChargeUsd`) in the run options when your client offers it.

### 🧰 More from architek.earth

**Jobs, companies and people**

- Google Jobs Scraper — *you are here*
- [LinkedIn Jobs Scraper](https://apify.com/architekture/linkedin-jobs-monitor) — descriptions, salaries, seniority
- [Indeed Scraper](https://apify.com/architekture/indeed-scraper) — jobs, salaries, descriptions
- [Y Combinator Scraper](https://apify.com/architekture/yc-companies-scraper) — companies, founders, jobs

**Search, travel and trends**

- [Google Shopping Scraper](https://apify.com/architekture/google-shopping-scraper) — prices, merchants and offers
- [Google Trends Scraper](https://apify.com/architekture/google-trends-scraper) — trending searches, traffic, related queries
- [Google Hotels Scraper](https://apify.com/architekture/google-hotels-scraper) — hotel prices, ratings, amenities

Full catalogue: [github.com/architek-earth](https://github.com/architek-earth).

architek.earth · code like concrete

### 🙋 Support & legal

Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.

This actor collects only publicly available data from Google search result pages (google.com, the Jobs tab), the same pages any visitor sees without logging in. It does not bypass authentication. It is not affiliated with or endorsed by Google. Job postings are published by employers and job boards. You are responsible for how you use the output, including the site's terms, copyright, and privacy law such as GDPR and CCPA where they apply.

### 📝 Changelog

- **2026-10-25** — Five input recipes, a head-to-head table, n8n and Make imports and MCP setup for Claude and Cursor added to this page; output and prices unchanged.
- **2026-10-25** — \[internal] Studio core 1.0.5 (from 1.0.4). A Google 403 or 429 is now tried on a fresh Google SERP proxy connection up to two more times (3 tries in all, no extra retry on top) before the search ends as a free `BLOCKED` status row; input, output and prices are unchanged.
- **2026-10-24** — First version: Google Jobs search in the US with full descriptions, job highlights and direct apply links; `expandQueries` for up to 7 searches per query with jobs deduplicated by `jobId`; hiring watch mode; resumable runs.

# Actor input Schema

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

1 to 50 Google Jobs searches, as you would type them into Google, e.g. "nurse jobs near Chicago, IL" or "remote data analyst jobs". Each search returns up to 10 jobs (Google shows no more to this route). US jobs only in this version.

## `expandQueries` (type: `boolean`):

Also run 6 refinements of each query: "<query> in the last 3 days", "<query> remote", "senior <query>", "entry level <query>", "<query> full time" and "<query> contract". Jobs are deduplicated by jobId, so you pay only for unique jobs (57 unique from 7 searches in testing).

## `incrementalMode` (type: `boolean`):

Deliver and charge only jobs not delivered before for this stateKey. Needs a stateKey.

## `stateKey` (type: `string`):

Any name you choose, reused on every run of the same searches. Required for incrementalMode; also lets a stopped run resume without re-charging.

## `feedback` (type: `string`):

Optional note for the maintainers. It is logged and read by a human, and it never changes output.

## Actor input object example

```json
{
  "queries": [
    "software engineer jobs near Austin, TX"
  ],
  "expandQueries": false,
  "incrementalMode": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "queries": [
        "software engineer jobs near Austin, TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("architekture/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 jobs near Austin, TX"] }

# Run the Actor and wait for it to finish
run = client.actor("architekture/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 jobs near Austin, TX"
  ]
}' |
apify call architekture/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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