# Google Jobs Scraper — Google Jobs API & Job Postings | $2.50/1k (`glasswing/google-jobs-scraper`) Actor

Scrape Google Jobs: title, company, location, salary parsed to min/max, job type, posting date, full description, job highlights and every apply link (LinkedIn, Indeed, company sites). 14 countries, proxy included. CSV, JSON, Excel.

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

## Pricing

from $2.50 / 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.

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 Scraper do?

Google Jobs Scraper reads **Google Jobs** (the "Jobs" tab of Google Search) and turns every listing into one clean row: job title, company, location, the job board Google found it on, salary, job type, posting date, Google's job highlights, the **full job description** and every **apply link** (LinkedIn, Indeed, ZipRecruiter, Glassdoor, the company's own careers page and more).

Google Jobs collects postings from thousands of job boards and career sites, so one search here covers what would otherwise take a dozen scrapers. Type a keyword and a location, pick a country, and you get a Google Jobs API-style dataset in minutes, ready for CSV, Excel, JSON or your own database.

- **Try it:** the prefilled searches (software engineer and data analyst jobs in New York) return 20 jobs in under a minute.
- **Reliable by design:** every run goes through Apify's Google SERP proxy, which is included in the price, and duplicate jobs are removed before you pay for them.

### Use cases for this Google Jobs scraper

- **Job aggregators and job boards** - fill a niche board with fresh postings from every source Google indexes, with direct apply links.
- **Recruiters and staffing agencies** - see which companies are hiring for a role in a city, how they pay and which boards they post on.
- **Labour-market and salary research** - track demand and pay ranges by title, city and country over time.
- **Sales and lead generation** - companies that are hiring are companies with budget; use the company name and job title as a hiring-intent signal.
- **AI agents and RAG pipelines** - plain-text descriptions and structured highlights are ready to embed or summarise.
- **Automation** - schedule a daily run and send new jobs to Google Sheets, Airtable, Slack or a CRM via Make, n8n or Zapier.

### What data can Google Jobs Scraper extract?

| Field | Example | Notes |
|---|---|---|
| `title` | Sr Software Engineer I | Job title |
| `companyName` | American Express | Hiring company |
| `location` | New York, NY | As Google shows it |
| `via` | LinkedIn | The job board Google found the listing on |
| `postedAgo` / `postedDate` | 3 days ago / 2026-10-13 | `postedDate` is computed from the relative age |
| `scheduleType` | Full-time | Full-time, Part-time, Contractor, Internship ... |
| `salary` | 123,000-215,250 a year | Salary text when Google shows one (about 1 job in 4 to 1 in 3) |
| `salaryMin` / `salaryMax` / `salaryPeriod` / `salaryCurrency` | 123000 / 215250 / year / USD | Parsed from `salary` |
| `workFromHome` | true | When Google tags the job as work from home |
| `benefits` | \["Dental insurance", "Health insurance"] | Benefit tags |
| `tags` | \["3 days ago", "Full-time", ...] | Every tag Google shows, unchanged |
| `qualifications` / `responsibilities` / `benefitsHighlights` | \["Bachelor's degree in ..."] | Google's "Job highlights" lists |
| `description` | Job Description\n\nAmerican Express ... | Full plain-text description |
| `applyOptions` | \[{"source": "LinkedIn", "url": "https://..."}] | Every apply link; `direct: true` marks "Apply directly on ..." |
| `applyUrl` | https://www.linkedin.com/jobs/view/... | First apply link |
| `jobId` | GHGNMW4tQ6R0tlf3AAAAAA== | Google's id for the listing; unique within a run |
| `url` / `shareLink` | https://www.google.com/search?... | The listing in Google Jobs (short link / Google's share link) |
| `companyLogo` | https://encrypted-tbn0.gstatic.com/... | Logo thumbnail |
| `query`, `searchLocation`, `country`, `searchUrl` | software engineer, New York, NY, us | The search that found the job |
| `status`, `error`, `scrapedAt` | ok | See below |

Field coverage on the first 20-job run: title, company, location, via, description, apply links, job type and posting age 100%, job highlights 95-100%, salary 35%.

#### Result status (tri-state output)

Every row has a `status`:

- `ok` - a job was extracted. Only these rows are billed.
- `not_found` - Google has no jobs for the search (it says "It looks like there aren't any Jobs matches"). Free.
- `error` - a results page could not be read after retries; `error` says why. Free.

### How to scrape Google Jobs with this Actor

1. **Enter keywords** - one job title or skill per line, for example `nurse` or `python developer`. Each line is one search.
2. **Set a location and country** - a city, region or `Remote`; leave the location empty to search the whole country.
3. **Pick a date filter and Maximum jobs** - for example past week and 200 jobs.
4. **Run** - jobs appear in the dataset as they are found. Export them as CSV, Excel, JSON or HTML, or read them through the API.

Google shows 10 jobs per results page and does not let anyone page further without a browser. For deeper searches the Actor automatically runs variants of your search (past week, past day, full time, remote, entry level, senior and more) and removes duplicates. Variants start only after the first page has returned at least 4 new jobs in your date window, run one or two at a time, and stop as soon as you have enough jobs or a variant adds fewer than 3 new ones. A run makes at most max(2, ceil(maxItems / 10) x 2.5) Google requests (5 for 20 jobs, 25 for 100).

With several keywords, the searches are tried in turn, not all at once (at most two at a time). A run stops early when several searches return nothing: after 3 searches in a row without a new job in your date window, the remaining keywords are not searched. Further searches also wait until the jobs already found cover the extra Google requests, so a list of niche keywords in a small town may search only the first one or two. The run's status message says how many searches were not run and the run log names them. Expect roughly 50-150 different jobs per keyword and location; add more keywords or locations to go wider.

### Input

| Field | What it does |
|---|---|
| `keywords` | Job titles or keywords, one search each. "jobs" and the location are added for you. |
| `location` | City, state or region, e.g. `New York, NY`, `London`, `Bangalore`, `Remote`. Empty = the whole country. |
| `country` | `us`, `uk`, `ca`, `in`, `sg`, `za`, `ph`, `ae`, `br`, `ng`, `my`, `hk`, `ke`, `pk`. |
| `datePosted` | `any`, `day` (past 24 hours, Google's "1 day ago" included), `week`, `month`. Every row is checked against the window; older jobs, and jobs Google shows without a posting age, are left out and never charged. |
| `maxItems` | Maximum jobs in total, split evenly over the searches. |
| `startUrls` | Optional Google search or Google Jobs URLs; each is one search. The prefilled example is skipped while Keywords has entries. |

Example input (the prefill):

```json
{
    "keywords": ["software engineer", "data analyst"],
    "location": "New York, NY",
    "country": "us",
    "datePosted": "any",
    "maxItems": 20
}
```

Several searches at once:

```json
{
    "keywords": ["registered nurse", "medical assistant", "pharmacist"],
    "location": "Chicago, IL",
    "country": "us",
    "datePosted": "week",
    "maxItems": 300
}
```

### Output

A real row from the prefilled run (description and lists shortened):

```json
{
    "url": "https://www.google.com/search?q=software+engineer+jobs+in+New+York%2C+NY&ibp=htl%3Bjobs&htidocid=GHGNMW4tQ6R0tlf3AAAAAA%3D%3D",
    "status": "ok",
    "scrapedAt": "2026-10-16T16:00:25.505Z",
    "jobId": "GHGNMW4tQ6R0tlf3AAAAAA==",
    "title": "Sr Software Engineer I",
    "companyName": "American Express",
    "location": "New York, NY",
    "via": "LinkedIn",
    "postedAgo": "3 days ago",
    "postedDate": "2026-10-13",
    "scheduleType": "Full-time",
    "salary": "123,000-215,250 a year",
    "salaryMin": 123000,
    "salaryMax": 215250,
    "salaryPeriod": "year",
    "salaryCurrency": "USD",
    "benefits": ["Dental insurance", "Health insurance"],
    "tags": ["3 days ago", "123,000-215,250 a year", "Full-time", "Dental insurance", "Health insurance"],
    "qualifications": [
        "Bachelor's degree in Computer Science, Computer Engineering, or a related technical discipline, or equivalent practical experience"
    ],
    "responsibilities": [
        "In this role, you will have the opportunity to solve complex technical challenges, influence engineering standards and best practices ..."
    ],
    "benefitsHighlights": ["Competitive base salaries", "Bonus incentives"],
    "description": "Job Description\n\nAmerican Express Platform Services builds and delivers enterprise platforms that enable business-critical applications to move faster from concept to production ...",
    "applyOptions": [
        { "source": "LinkedIn", "url": "https://www.linkedin.com/jobs/view/sr-software-engineer-i-at-american-express-4478178525?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic" },
        { "source": "Ladders", "url": "https://www.theladders.com/job/sr-software-engineer-i-americanexpress-new-york-ny_89351699?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic" }
    ],
    "applyUrl": "https://www.linkedin.com/jobs/view/sr-software-engineer-i-at-american-express-4478178525?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
    "shareLink": "https://www.google.com/search?ibp=htl;jobs&q=software+engineer+jobs+in+New+York,+NY&htidocid=GHGNMW4tQ6R0tlf3AAAAAA%3D%3D&...",
    "companyLogo": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR0br66iRzv7OfSZthKWVwvbMLO79tsHGAI6tda&s=0",
    "query": "software engineer",
    "searchLocation": "New York, NY",
    "country": "us",
    "searchUrl": "https://www.google.com/search?q=software+engineer+jobs+in+New+York%2C+NY+in+the+last+week&udm=8&hl=en&gl=us"
}
```

A missing field is honest: it means Google did not show it for that job, never a guess. The Actor never outputs recruiter or poster names, emails or phone numbers; contact details inside descriptions are replaced with `[email removed]`, `[phone removed]`, `[profile link removed]` or `[name removed]`. Names of staff quoted in testimonials ("A word from our team", "- Jane Doe, Staff Nurse") are replaced with `[name removed]` too; the quote itself stays.

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

Pay per result: **$2.50 per 1,000 jobs** plus a $0.005 start fee per run. The Google SERP proxy and platform usage are included.

| Event | Price | Charged when |
|---|---|---|
| Actor start | $0.005 | Once per run (default 512 MB; memory is capped at 1 GB, which this Actor never needs more than) |
| Job | $0.0025 | One job with status `ok` saved to the dataset |

Examples: 100 jobs cost about $0.26, 1,000 jobs about $2.51, 10,000 jobs about $25. Rows with status `not_found` or `error` and duplicate jobs are never charged. The Actor stops gracefully when your run's maximum charge is reached.

### Integrations, exports and API access

Download results as CSV, Excel, JSON, XML or HTML from the run's Storage tab, or read them with the Apify API:

```bash
curl "https://api.apify.com/v2/acts/glasswing~google-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST -H "Content-Type: application/json" \
  -d '{"keywords": ["data analyst"], "location": "London", "country": "uk", "maxItems": 50}'
```

The Actor also works from Make, n8n, Zapier, Google Sheets and any MCP client or AI agent (it accepts plain JSON input; every field has a default).

### Tips

- One keyword per line works better than one long query: `nurse` and `nurse practitioner` are two searches with different results.
- Put your most productive keyword first: searches run in the order you list them, and a run stops early when several return nothing.
- Use `datePosted: day` on a schedule to collect only new jobs every day. Each row is checked against the window, so a stale job is never written or charged; a day window usually returns fewer jobs than `any`.
- For a whole country, leave `location` empty; for a metro area, give the main city ("Dallas, TX").
- Pasting a Google Jobs URL keeps its query and date filter (a past-day, week or month filter in the URL is applied the same way as `datePosted`); the Actor reads it in English.

### Limitations

- **Countries:** Google offers Google Jobs in the countries listed above. It is not available in the EU/EEA, Australia, New Zealand, Mexico or Japan, so those are not supported.
- **Depth:** Google shows 10 jobs per results page and about 50-150 different jobs per search across the variants. For thousands of jobs, use many keywords and locations.
- **Language:** pages are read with Google set to English; job texts stay in the language they were posted in.
- **Salary:** shown by Google for roughly a quarter to a third of jobs; `salaryMin`/`salaryMax` are parsed from that text.
- **Posting date:** `postedDate` is computed from Google's relative age ("3 days ago"), so it is accurate to the day.
- **Narrow searches:** when the first page of a search returns fewer than 4 new jobs in your date window, no variants are run, so a narrow title in a small town with `datePosted: day` can return only a few jobs. Three Google pages in a row without a new job also end the run, and three searches in a row without a new job end the keyword list.
- **Searches with no jobs:** a search Google has no jobs for makes one Google request (two when Google's first answer was incomplete) and writes one free `not_found` row; you pay only the $0.005 start fee. However many keywords you give, a run that finds nothing stops after at most 3 searches (2 when Google answers slowly).
- **Many keywords:** each keyword needs at least one Google request, and a run makes at most max(2, ceil(maxItems / 10) x 2.5) of them. Keywords are searched in turn and only while the run still needs jobs; keywords left over (request cap reached, 3 empty searches in a row, or too few jobs found so far to pay for more searches) are counted in the status message and named in the run log. Raise `maxItems` or split them over several runs.

### FAQ

#### Is it legal to scrape Google Jobs?

The Actor reads only public Google Jobs results, without logging in. The job postings belong to the employers and job boards that published them. Check Google's terms and your local law for your use case, and see the notice below about personal data.

#### Can I use this Actor from an AI agent or MCP client?

Yes. Every field has a default, so a call with just `{"keywords": ["welder"]}` works. Results come back as structured JSON.

#### Why did I get fewer rows than `maxItems`?

Google ran out of different jobs for that search, the first page had fewer than 4 new jobs in the date window (then no variants run), the variants stopped adding new ones, or the run stopped searching further keywords because the earlier ones returned nothing or very little (the status message says how many were not run). Add more keywords or nearby locations, or widen `datePosted`.

#### Does the Actor return duplicate jobs?

No. The same job often appears under several variants of a search; it is written and charged once per run, identified by Google's `jobId`.

#### Do I need a proxy or a Google account?

No. The Google SERP proxy is set up and paid for by the Actor, and no Google account is used.

#### What if a field is missing?

Google did not show it for that listing. Fields are omitted rather than guessed.

### Related Actors

- [LinkedIn Jobs Scraper](https://apify.com/glasswing/linkedin-jobs-scraper) - LinkedIn job postings with full descriptions and applicant counts.
- [ATS Jobs Scraper](https://apify.com/glasswing/ats-jobs-scraper) - jobs straight from companies' Greenhouse, Lever, Ashby and other career pages.
- [Dice Jobs Scraper](https://apify.com/glasswing/dice-jobs-scraper) - US tech and IT jobs from Dice.com.
- [Remote Jobs Scraper](https://apify.com/glasswing/remote-jobs-scraper) - remote tech jobs from several remote-only boards, merged and deduplicated.
- [Jobstreet Scraper](https://apify.com/glasswing/jobstreet-scraper) - jobs in Southeast Asia (Malaysia, Singapore, Philippines, Indonesia).
- [Seek Jobs Scraper](https://apify.com/glasswing/seek-jobs-scraper) - jobs in Australia and New Zealand, where Google Jobs is not available.
- [Google Ads Transparency Scraper](https://apify.com/glasswing/google-ads-transparency-scraper) - the ads a company runs on Google.
- [Keyword Suggestions Scraper](https://apify.com/glasswing/keyword-suggestions-scraper) - Google autocomplete keyword ideas.
- [Domain Intelligence Report](https://apify.com/glasswing/domain-intelligence-report) - DNS, mail and tech facts about a company's domain.
- [Indeed Scraper](https://apify.com/glasswing/indeed-jobs-scraper) - use it for Indeed job postings in 22 countries with parsed salary ranges and full descriptions.
- [Glassdoor Scraper](https://apify.com/glasswing/glassdoor-jobs-scraper) - use it for Glassdoor job listings with company ratings and salary estimates.

### Legal and data-protection notice

This Actor extracts only data that Google Jobs publishes publicly; it does not extract private user data such as e-mail addresses, phone numbers, gender or precise location, and it does not log in or circumvent access controls. However, your results could still contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with Google's terms of service and applicable law when using the extracted data.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Google or its owners. All trademarks belong to their respective owners.

# Changelog

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

# Actor input Schema

## `keywords` (type: `array`):

Job titles or keywords, one per line, as you would type them into Google (for example `nurse`, `python developer`, `warehouse associate`). Each line is one search; "jobs" and the location are added for you.

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

City, state or region, for example `New York, NY`, `London`, `Bangalore`, `Remote`. Leave empty to search the whole country.

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

Which country's Google Jobs results to read. Google does not offer Google Jobs in the EU/EEA, Australia, New Zealand, Mexico or Japan, so those countries are not listed.

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

Only jobs posted within this period. Every row is checked against it: older jobs, and jobs Google shows without a posting age, are left out and not charged.

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

Stop after this many jobs in total (split evenly over the searches). Google shows roughly 50-150 different jobs per search; for more, add more keywords or locations. Each saved job is one billable result.

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

Optional. Google search or Google Jobs URLs (for example `https://www.google.com/search?q=barista+jobs+seattle&udm=8`), one per line. Each URL is one search, read in English. The prefilled example is skipped while Keywords has entries.

## Actor input object example

```json
{
  "keywords": [
    "software engineer",
    "data analyst"
  ],
  "location": "New York, NY",
  "country": "us",
  "datePosted": "any",
  "maxItems": 20,
  "startUrls": [
    "https://www.google.com/search?q=barista+jobs+seattle&udm=8"
  ]
}
```

# Actor output Schema

## `results` (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 = {
    "keywords": [
        "software engineer",
        "data analyst"
    ],
    "location": "New York, NY",
    "maxItems": 20,
    "startUrls": [
        "https://www.google.com/search?q=barista+jobs+seattle&udm=8"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("glasswing/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 = {
    "keywords": [
        "software engineer",
        "data analyst",
    ],
    "location": "New York, NY",
    "maxItems": 20,
    "startUrls": ["https://www.google.com/search?q=barista+jobs+seattle&udm=8"],
}

# Run the Actor and wait for it to finish
run = client.actor("glasswing/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 '{
  "keywords": [
    "software engineer",
    "data analyst"
  ],
  "location": "New York, NY",
  "maxItems": 20,
  "startUrls": [
    "https://www.google.com/search?q=barista+jobs+seattle&udm=8"
  ]
}' |
apify call glasswing/google-jobs-scraper --silent --output-dataset

```

## MCP server setup

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