# Google Jobs Search Scraper (`googleapi/google-jobs-search-scraper`) Actor

Collect public Google Jobs listings with full descriptions, structured compensation, posting-date precision, application choices, and job requirements.

- **URL**: https://apify.com/googleapi/google-jobs-search-scraper.md
- **Developed by:** [Google API](https://apify.com/googleapi) (community)
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Google Jobs Search Scraper do?

This Actor is a programmatic alternative to manually searching public [Google Jobs results](https://www.google.com/search?udm=8\&q=jobs). It returns one business-data row per job posting and can extract the expanded description, visible application choices, compensation, date text, and source-backed requirements. It does not use private Google APIs, access private user data, or bypass access boundaries.

Browser mode is enabled by default to open matching public job details and capture expanded descriptions. Base job listings remain available if optional detail-page information cannot be collected.

### Search input

The main input is a job `query`, optionally combined with a `location`, `country`, and `language`. Batch queries, Google Jobs `startUrls`, employment and experience filters, page limits, and a salary floor are also supported. See the Input tab for all available options.

```json
{
  "query": "software engineer",
  "location": "Seattle, WA",
  "country": "us",
  "maxItems": 25,
  "maxPages": 5,
  "includeDescriptionHtml": true
}
```

`employmentTypes` and `jobRequirements` are single-select strings in the Apify form. API callers may provide either a string or an array. `startUrls` must be HTTPS Google Jobs search URLs; arbitrary websites are not accepted as search URLs.

`useBrowser` defaults to `true` and expands public job details. `proxyConfiguration` applies in browser mode; HTTP mode does not use it. The Actor does not solve CAPTCHAs or bypass access boundaries. `resolveApplyUrls` and `enrichFromSourcePages` are off by default; enable them only when you need resolved application destinations or additional job details from public employer pages.

### Use cases

- Build job-market and hiring-demand snapshots from public search results.
- Compare role requirements, experience levels, and compensation ranges.
- Create recruiting research datasets while retaining each visible application option and the complete expanded description.

### Dataset contract

Compensation parsing excludes company asset/valuation figures and prefers explicit salary lines. Source-specific question headings and team/benefit headings keep company background, qualifications and duties separate; certification names require whole-token matches. Employer-prefixed source location labels are preserved separately from the cleaned location. Explicit mixed on-site/remote weekly schedules are classified as hybrid without inventing a remote boolean.

Each row contains values exposed by Google Jobs or, when enrichment is enabled, public source-page structured data. Missing facts are not replaced with invented values. Compatibility aliases include `jobTitle`/`title`, `employerName`/`company`/`companyName`, and `jobLocation`/`location`.

Available fields cover:

- **Job identity and employer:** `jobId`, `jobIdSource`, `jobIdIsDerived`, `jobTitle`, `employerName`, `companyName`, `companyDescription`, `companyWebsite`, `companyRating`, `companyReviewCount`.
- **Employer overview copy:** `companyDescription` is populated only when the expanded job description has a clearly labeled “About \[employer]”, “About Us”, or company-overview section; it is not inferred from unrelated prose.
- **Company review aggregates:** `companyReviewSummaries` retains each supported review platform, visible rating and scale, and the displayed review-count text. Compact counts such as `1.3K` keep their source text and are marked estimated when normalized to a number.
- **Search result and location:** `jobPublisher`, `sourcePlatform`, `jobLocation`, `jobLocationText`, `jobCity`, `jobState`, `jobCountry`, `locations`, and source-provided coordinates.
- **Description:** full `jobDescription` and `description`, optional cleaned `jobDescriptionHtml`, a separate 500-character `jobDescriptionPreview`, and `descriptionSections` for unclassified sections and notices. The full description is not truncated to the preview length.
- **Description-derived sections:** `responsibilities`/`responsibilitiesText`, `qualifications`/`qualificationsText`, `benefits`/`benefitsList`/`benefitsHighlightsText`, and extracted `skills`, `certifications`, and `requiredLanguages`. Common headings such as “The role entails,” “What we are looking for in you,” and “What we offer colleagues” are classified; role overview, employer overview, hiring tags, requisition labels, and equal-opportunity notices stay in `descriptionSections` instead of being mixed into requirements or duties.
- **Dates:** exact source text in `postedAtText` (also `postedAt` and compatibility aliases), `postedAtPrecision`, `postedAtIsEstimated`, `postedDateEstimated`, and `postedAtTimestamp`. Relative dates are labeled estimated; date-only source values are not given a fabricated midnight timestamp.
- **Compensation:** raw `salary` and `salarySourceText`, normalized bounds and midpoint (`salaryMin`, `salaryMax`, `salaryValue`), ISO currency, `salaryPeriod`, and `salaryType` (`employer_stated` or `estimated`) when salary evidence is present. Unsupported placeholders such as `unspecified` are omitted; a displayed estimate stays labeled as an estimate.
- **Requirements and work:** tri-state `degreeRequired` and `isRemote`, `educationText`, `educationLevels`, `experienceRequirements`, `experienceYears`, month bounds, `seniorityLevel`, and `workArrangement` (`remote`, `hybrid`, `on_site`, or `unknown`). `experienceYears` is emitted only with explicit public wording that supports its numeric bounds; unknown or placeholder bounds are omitted. Unknown booleans remain `null` rather than being guessed as `false`.
- **Applications:** `applyOptions` preserves every visible apply choice with its label, platform, original URL, optional resolved URL, destination domain, employer-site assessment, and direct-apply evidence. `jobApplyLink` is a convenience alias for the first option.
- **Structured source-page facts:** when opt-in enrichment finds matching Schema.org data, fields can include `requisitionId`, `department`, `validThrough`, `totalJobOpenings`, `jobStartDate`, and `workHours`.

The following is an illustrative selected-field fragment, not a claim of a live result or a promise that every field is present. The Actor omits facts the source does not expose; sparse listings may have fewer than 20 populated fields.

```json
{
  "jobTitle": "Senior Software Engineer",
  "title": "Senior Software Engineer",
  "employerName": "Example Employer",
  "company": "Example Employer",
  "companyName": "Example Employer",
  "companyDescription": "Example Employer builds tools for distributed engineering teams.",
  "companyRating": 3.8,
  "companyReviewCount": "12.4K",
  "companyReviewSource": "Example review platform",
  "companyReviewSummaries": [
    {
      "platform": "Example review platform",
      "rating": 3.8,
      "ratingText": "3.8/5",
      "ratingScale": 5,
      "reviewCount": 12400,
      "reviewCountText": "12.4K",
      "reviewCountIsEstimated": true
    }
  ],
  "jobPublisher": "Example Careers",
  "sourcePlatform": "Example Careers",
  "jobLocation": "Seattle, WA",
  "jobLocationText": "Seattle, WA",
  "jobCity": "Seattle",
  "jobState": "WA",
  "employmentType": "Full-time",
  "employmentTypeText": "Full-time",
  "postedAtText": "19 hours ago",
  "postedAtPrecision": "hour",
  "postedAtIsEstimated": true,
  "educationText": "No Degree Mentioned",
  "educationRequirements": "No Degree Mentioned",
  "educationSource": "google_visible",
  "degreeRequired": null,
  "salary": "$185,000 -$254,000",
  "salarySourceText": "For Seattle-based hires: Estimated annual salary of $185,000 -$254,000",
  "salaryMin": 185000,
  "salaryMax": 254000,
  "salaryValue": 219500,
  "salaryPeriod": "YEAR",
  "salaryType": "estimated",
  "workArrangement": "unknown",
  "isRemote": null,
  "jobApplyIsDirect": true,
  "applicationType": "Direct Apply",
  "applyPlatforms": "Example Employer Careers",
  "applyOptions": [
    {
      "platform": "Example Employer Careers",
      "label": "Apply directly on Example Employer Careers",
      "applicationType": "Direct Apply",
      "originalUrl": "https://careers.example-employer.com/apply/123",
      "resolvedUrl": null,
      "destinationDomain": "careers.example-employer.com",
      "isEmployerSite": true,
      "directApply": true
    }
  ],
  "jobApplyLink": "https://careers.example-employer.com/apply/123"
}
```

Failed searches and access boundaries appear in the run summary and logs rather than as job records.

### Run records and exports

The run summary and source-access information are available alongside the dataset in the Output tab.

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Input and pagination behavior

`startUrls` accepts HTTPS Google Jobs search URLs only. When you provide both `startUrls` and `query`/`queries`, the Actor processes the custom URLs first and then the generated searches; they are additive, not overrides. Generated searches receive the location/date/employment/requirements chips. `maxItems` is a global cap across the run; `maxPages` is applied separately to each target. In browser mode, each page budget is a bounded scroll/load iteration; in HTTP mode, it is a ten-result offset page. `page` selects the initial offset.

Records are deduplicated across targets by the Google document ID when present, otherwise by a deterministic hash of title, employer, location, and posting URL. `minSalary` is an annual lower-bound filter: a record must expose an annual minimum at or above the requested amount. Date and employment filters are sent to Google and checked against extracted values; `jobRequirements` is a Google search chip, not an independent classification guarantee. `directApplyOnly` requires both direct-apply evidence and employer/ATS-domain evidence.

#### Input examples

Basic search:

```json
{
  "query": "software engineer",
  "location": "Seattle, WA",
  "country": "us",
  "maxItems": 10,
  "maxPages": 2
}
```

Salary, employment, and experience filters (arrays are accepted through the API):

```json
{
  "query": "backend engineer",
  "minSalary": 120000,
  "employmentTypes": ["FULLTIME", "CONTRACTOR"],
  "jobRequirements": ["more_than_3_years_experience"],
  "datePosted": "week",
  "maxItems": 25
}
```

Multiple custom Google Jobs sources:

```json
{
  "startUrls": [
    { "url": "https://www.google.com/search?udm=8&q=software+engineer" },
    { "url": "https://www.google.com/search?udm=8&q=data+analyst" }
  ],
  "maxItems": 40,
  "maxPages": 3
}
```

Use HTTP instead of headless browser extraction, and omit description HTML:

```json
{
  "query": "data analyst",
  "page": 2,
  "maxPages": 1,
  "maxItems": 10,
  "useBrowser": false,
  "includeDescriptionHtml": false
}
```

Optional application-link resolution and source-page enrichment are disabled by default. When enabled, `maxSourcePagesPerJob` controls how many public source pages are checked per job (default 1, maximum 3).

#### Input reference

| Field | Type and default | Behavior |
|---|---|---|
| `query`, `queries` | string, array | Single search term plus up to 50 batch terms; terms are trimmed and bounded. |
| `startUrls` | array of `{ "url": "..." }` | Up to 50 HTTPS Google Jobs search URLs; processed before generated queries. |
| `location`, `country`, `language` | strings; language defaults to `en` | Location is added to generated searches; country/language become Google search parameters. |
| `datePosted` | enum, defaults to `all` | `all`, `today`, `3days`, `week`, or `month`. |
| `workFromHome` | boolean, defaults to `false` | Adds a remote search term and excludes extracted records not classified remote. |
| `employmentTypes`, `jobRequirements` | string in the form; API also accepts arrays | Adds Google Jobs filter chips; see the Input tab for allowed values. |
| `page`, `maxItems`, `maxPages` | integers; defaults `1`, `50`, `10` | Page starts at 1; item cap is global; page/scroll budget applies per target. |
| `minSalary` | integer, optional | Annual minimum compensation floor; records without an annual lower bound do not pass. |
| `directApplyOnly` | boolean, defaults to `false` | Requires both direct-apply evidence and employer/ATS destination evidence. |
| `useBrowser` | boolean, defaults to `true` | Browser mode expands detail panes; HTTP mode uses Google’s ten-result offset parameter. |
| `includeDescriptionHtml` | boolean, defaults to `true` | Set to `false` to omit the HTML description while retaining clean text. |
| `proxyConfiguration` | object, optional | Used by browser mode only; ignored with a warning in HTTP mode. |
| `resolveApplyUrls`, `enrichFromSourcePages` | booleans, defaults to `false` | Opt-in external URL resolution and matching JobPosting JSON-LD enrichment. |
| `maxSourcePagesPerJob` | integer, defaults to `1`, range 1–3 | Maximum destination pages attempted for enrichment when enabled. |

There is no sorting input. These controls affect search construction, filtering, output selection, or optional enrichment as described above; they do not create fields that the source did not provide.

### How to scrape Google Jobs

1. Open this Actor's Input tab and enter a role in `query`, or provide Google Jobs search pages in `startUrls`.
2. Add an optional location, country, date, employment, experience, or salary filter.
3. Start with a modest `maxItems` and `maxPages`; keep browser mode enabled when expanded job descriptions are important.
4. Run the Actor, review the dataset and run summary, then export or integrate the dataset through the Actor API tab.

Use Apify scheduling, run history, and integrations for repeated public snapshots. Results depend on the visible Google Jobs page, region, query, and access availability.

### Run sizing, cost, and support

Browser extraction is enabled by default because job details expand dynamically. More targets, pages/scroll iterations, and results consume more compute; browser mode is generally heavier than HTTP mode. Optional application-link resolution and source-page enrichment add bounded network requests. No fixed run-cost estimate is provided because resource use depends on the input and the Apify plan.

The Actor returns only fields visible in Google Jobs or found in explicitly enabled, identity-matched source-page structured data. Listings and fields vary by query, region, and access availability; the Actor does not bypass CAPTCHA or other access boundaries. Use the data in accordance with Google and destination-site terms and applicable privacy requirements.

This Actor is not affiliated with Google or any employer or job publisher. Use public information responsibly and follow Google/destination-site terms, applicable rate limits, privacy rules, and law. Listings may contain personal information published by employers; do not use it without a lawful basis. For support, use this Actor's Apify Issues tab and include a run ID, sanitized input, and relevant log excerpts. Use the API tab for programmatic integrations; never share tokens or cookies in an issue. On an access boundary, the Actor stops without adding an error job. An empty dataset can mean no visible matching cards or restricted access, not that Google has no such jobs.

# Actor input Schema

## `query` (type: `string`):

Job title or keyword to search (e.g. 'Software Engineer', 'Data Analyst', 'Marketing Manager').

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

Multiple search queries to run in a single batch execution.

## `startUrls` (type: `array`):

Public Google Jobs search URLs (for example https://www.google.com/search?udm=8\&q=software+engineer).

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

Specific city, state, or metropolitan area to search (e.g. 'New York, NY', 'London, UK', 'Berlin, Germany').

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

Two-letter ISO 3166-1 alpha-2 country code (e.g. 'us', 'gb', 'de', 'in', 'ca', 'au', 'fr'). Leave blank for automatic location.

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

Two-letter ISO 639-1 language code (e.g. 'en', 'de', 'es', 'fr').

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

Filter jobs by when they were published.

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

Filter for remote, telecommute, or work-from-home positions only.

## `employmentTypes` (type: `string`):

Filter by employment type.

## `jobRequirements` (type: `string`):

Filter by required experience level or educational degree.

## `page` (type: `integer`):

Initial search results page to start scraping from (10 jobs per page, 1 = first page).

## `minSalary` (type: `integer`):

Optional minimum salary floor (e.g. 50000, 80000, 120000).

## `directApplyOnly` (type: `boolean`):

Only return job listings with direct application links on the hiring company's career site.

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

Maximum number of job postings to collect.

## `maxPages` (type: `integer`):

Maximum pagination pages to navigate per query (10 jobs per page).

## `includeDescriptionHtml` (type: `boolean`):

Include rich HTML markup with paragraphs, bullet points, and formatting in addition to clean text.

## `requestTimeoutSecs` (type: `integer`):

Maximum time to wait for Google Jobs page responses.

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

Optional Apify proxy settings used only when useBrowser is true; HTTP mode ignores this setting. Access boundaries are not bypassed.

## `useBrowser` (type: `boolean`):

Execute in headless Chromium for dynamic expansion and full details extraction.

## `resolveApplyUrls` (type: `boolean`):

Resolve Google redirect application URLs to their destination pages. Disabled by default; destination requests are safety-checked.

## `enrichFromSourcePages` (type: `boolean`):

Fetch linked destination pages for Schema.org JobPosting data (e.g. requisition ID, department, locations, valid-through date). Disabled by default.

## `maxSourcePagesPerJob` (type: `integer`):

Maximum number of destination links to attempt enriching per job posting.

## Actor input object example

```json
{
  "query": "software engineer",
  "language": "en",
  "datePosted": "all",
  "workFromHome": false,
  "employmentTypes": "",
  "jobRequirements": "",
  "page": 1,
  "directApplyOnly": false,
  "maxItems": 50,
  "maxPages": 10,
  "includeDescriptionHtml": true,
  "requestTimeoutSecs": 30,
  "useBrowser": true,
  "resolveApplyUrls": false,
  "enrichFromSourcePages": false,
  "maxSourcePagesPerJob": 1
}
```

# Actor output Schema

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

No description

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

No description

## `runHealth` (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 = {
    "query": "software engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("googleapi/google-jobs-search-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 = { "query": "software engineer" }

# Run the Actor and wait for it to finish
run = client.actor("googleapi/google-jobs-search-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 '{
  "query": "software engineer"
}' |
apify call googleapi/google-jobs-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,googleapi/google-jobs-search-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/wdgn454JesgrgQlFt/builds/1YEsCDWQbJU6YIPiM/openapi.json
