# Google Jobs Scraper: LinkedIn, Indeed, Glassdoor jobs (`famed_bonobo/google-jobs-scraper`) Actor

Job listings from LinkedIn, Indeed, Glassdoor, ZipRecruiter and company career sites, gathered by Google Jobs: full description, salary as numbers, direct apply link, distance from a city and new-job alerts. No login or cookies.

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

## Pricing

from $1.05 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Google Jobs Scraper

Get job listings from [Google Jobs](https://www.google.com/search?q=jobs\&udm=8), the job search built into Google that gathers postings from LinkedIn, Indeed, Glassdoor, ZipRecruiter, company career sites and hundreds of other boards. Type searches the way you would on Google, such as **"software engineer jobs in Austin"**, and get clean records with title, company, location, salary, job type, posting age, the full description, Google's job highlights and **direct links to every site where you can apply**.

### What you can use it for

- **Job boards and aggregators**: fill your listings with fresh jobs for any role and city.
- **Recruiting and sales intelligence**: see which companies are hiring for which roles, where and at what salary.
- **Labor market research**: track demand, salaries and job types by role, region and country.
- **Job alerts and AI assistants**: feed new postings into alerts, newsletters or an AI job-search agent.

### What data you get

| Field | Example |
|---|---|
| Title, company, location | System Software Engineer - Performance, NVIDIA, Austin, TX |
| Source | LinkedIn |
| Posted, job type, salary | 21 hours ago, Full-time, $140K–$200K a year |
| Salary as numbers | min 140000, max 200000, USD, year (also for "De 20 mil € a 24 mil € al año", "14,01 € por hora", "₹6L–₹10L") |
| Posting time | estimated timestamp, such as 2026-10-15T16:00:00Z for "17 hours ago", in any language |
| Other details | No degree mentioned, Health insurance, Paid time off |
| Highlights | Qualifications (11), Benefits (3), Responsibilities (7) |
| Description | the full posting text, with line breaks |
| Apply options | LinkedIn, Glassdoor, SimplyHired, Digitalhire, each with its direct job URL, Google's main option and its "Apply directly" label |
| Best apply link | the direct URL of Google's main option, such as jobs.ebayinc.com/us/en/job/R0076812/... |
| Occupation | O\*NET code 15-1132.00 (software developers) and job zone 4, as Google classifies the job |
| Company | Google Knowledge Graph id (/m/09rh\_ for NVIDIA) and logo |
| Same job on several sites | `clusterId`: equal ids are the same job, handy to remove duplicates |
| Location on the map | Google Maps link of the job location |
| Distance | kilometres from your location to the job's town, such as 50.9 for a job in Edwards when you search around Leadville, CO |
| Description as HTML | the posting with its lists and paragraphs, ready to display |
| Rank in Google's list | the job's position in the Google search that found it |

### How to use it

1. Type one or more searches, one per line: a role and a place, such as `registered nurse jobs Houston`, `marketing manager remote` or `desarrollador python Bogotá`.
2. Set **Country** to the country of the job market you search (for example `de` for jobs in Germany) and **Language** to the language of Google's labels.
3. Optionally use the same filters Google Jobs offers: posted within (24 hours, week, month), job type (full-time, part-time, contractor, internship), remote only and no degree required. You can also leave out companies (such as staffing agencies) or title words, keep only jobs that show a salary or pay at least a yearly amount (hourly and monthly salaries are counted for a full-time year), keep or leave out publishing sites (LinkedIn, Indeed...), and set the location once in its own field, with a **search radius** in kilometres around it.
4. Run it and download the jobs as JSON, CSV, Excel or HTML, or read them through the Apify API.

**How many jobs per search?** Google shows 10 jobs at a time. This scraper follows Google's own "more jobs" pages, so one search returns its whole list, usually 150 to 200 jobs, in Google's order. Past that it adds the filter searches Google prints on its own page (job types, remote, posting dates, in the page's language) and their combinations, with duplicates removed, so broad searches reach 1,000 or more. In our tests on Apify: 200 jobs in 46 seconds and 400 jobs in 19 seconds. Set **Max jobs per search** to how many you need; the scraper stops there and you pay only for those.

#### Input example

```json
{
  "queries": ["software engineer jobs in Austin", "data analyst jobs in Chicago"],
  "maxJobsPerQuery": 100,
  "country": "us",
  "language": "en"
}
```

#### Output example

```json
{
  "query": "software engineer jobs in Austin",
  "position": 2,
  "jobId": "bGaeJ4Gg9YLWWaYZAAAAAA==",
  "title": "System Software Engineer - Performance",
  "company": "NVIDIA",
  "location": "Austin, TX",
  "via": "LinkedIn",
  "postedAgo": "21 hours ago",
  "salary": null,
  "employmentType": "Full-time",
  "otherDetails": [],
  "highlights": {
    "Qualifications": ["5+ years of experience in system software development", "..."],
    "Benefits": ["..."],
    "Responsibilities": ["..."]
  },
  "description": "We are looking for a System Software Engineer ...",
  "descriptionIsComplete": true,
  "applyOptions": [
    {
      "label": "Apply on LinkedIn",
      "url": "https://www.google.com/goto?url=...",
      "directUrl": "https://www.linkedin.com/jobs/view/system-software-engineer-performance-at-nvidia-4478174889"
    },
    {
      "label": "Apply on Glassdoor",
      "url": "https://www.google.com/goto?url=...",
      "directUrl": "https://www.glassdoor.com/job-listing/jv?jl=1010294318621"
    }
  ],
  "foundWith": "software engineer jobs in Austin",
  "language": "en",
  "country": "us"
}
```

Texts such as "21 hours ago" or "Full-time" come in the language you choose. In some countries Google sends only a preview of the description; `descriptionIsComplete` tells you which case you got.

### Searching within a radius

Set **Location** and **Search radius (km)** to get the jobs around a place, not only in it. Google Jobs on its own keeps to the place you name, so the scraper also searches the towns inside the radius (the biggest first), measures each job's distance from your location and keeps only those within it. Every job carries `distanceKm`, so you can sort by distance or cut closer.

In our test, nurse jobs around Leadville, CO with 60 km found 37 jobs in Leadville itself, then completed the list with Fairplay (25 km) and Edwards (51 km). Jobs that name no place, such as "Anywhere", are left out of a radius search, and the log says how many.

Town locations come from [GeoNames](https://www.geonames.org) (CC BY 4.0), which lists every place with 500 or more people.

### Monitoring new jobs

Turn on **Only new jobs** and schedule the Actor (for example every morning). Each run stores only the jobs earlier runs did not store, so you pay only for new postings and your integrations (email, Slack, Google Sheets) get just what changed. Jobs that Google lists on several sites are matched by Google's own cluster id, so a repost on another board is not counted as new. The memory lives in a key-value store of your account named after the monitor; give it a **Monitor name** to share it between schedules, or leave it empty to keep one memory per set of searches.

### Pricing

**$1.50 per 1,000 jobs** stored. Platform usage, including the Google proxy, is included. You can cap the cost of any run with Apify's maximum charge setting; the scraper stops cleanly when the cap is reached.

### Reliability

- Uses Apify's Google SERP proxy, built for Google Search, so there are no captchas and no browser to break.
- **Speed:** each search's first page goes through the proxy (several copies at once, the quickest wins) and every following page loads in about half a second, so 200 jobs take under a minute and several searches run side by side.
- When Google answers without the jobs block, the scraper asks again before concluding there are no jobs.
- Each job is stored once per search, even when several filters find it; `foundWith` tells you which search variant found it.
- If one search fails, the others still finish, and the run status names the search that failed.
- Labels such as salary, job type and posting age are recognized by their icons, so they work in every language.

### FAQ

**Why did a search return no jobs?**
Google shows no jobs when the search does not look like a job search for that country. Add a role and a place, and set Country to the country of the jobs.

**Can I search in miles?**
The radius is in kilometres; multiply miles by 1.6 (25 miles = 40 km).

**Do the apply links work?**
Yes. Every option keeps Google's link and adds `directUrl`, the job page on the site itself (LinkedIn, Indeed, the company's careers page and so on).

**Is this legal?**
The scraper collects public job postings that employers publish to attract applicants; it does not collect data about job seekers. You are responsible for how you use the data and for complying with the laws and terms that apply to you.

### Also from this developer

- [Google Hotels Scraper](https://apify.com/famed_bonobo/google-hotels-scraper): hotel prices, ratings and the offer from every booking site.
- [Google Flights Scraper](https://apify.com/famed_bonobo/google-flights-scraper): every flight for any route and date, with Google's price insights.

### Feedback

Found a problem or need a field that is missing? Open an issue on the Issues tab and it will be answered quickly.

# Actor input Schema

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

What to search on Google Jobs, one search per line, as you would type it on Google: a role and a place, such as "software engineer in Austin" or "nurse jobs Madrid".

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

Optional. A city, region or country added to every search, such as "Denver, CO" or "Madrid". You can also write it inside each search instead. When it names a city or town, every job gets its distance from it.

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

Optional, needs Location. Jobs up to this many kilometres from the location (1 mile = 1.6 km): the scraper also searches the towns around it and keeps only jobs within the radius, each with its distance. Jobs with no place ("Anywhere") are left out. Leave empty to search Google's own area, which is usually the place itself.

## `maxJobsPerQuery` (type: `integer`):

Stop each search after this many jobs. One search reaches about 200 jobs; past that, the scraper adds the filter searches Google offers on its own page (job type, remote, posting date...) and their combinations, so broad searches reach 1,000 or more.

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

Only jobs posted in this period.

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

Only these job types (each one is its own Google search). Available on English and Spanish pages.

## `remoteOnly` (type: `boolean`):

Google's remote filter (English pages).

## `noDegreeOnly` (type: `boolean`):

Google's no-degree filter (English pages).

## `excludeCompanies` (type: `array`):

Leave out jobs whose company name contains any of these texts, such as staffing agencies.

## `excludeTitleWords` (type: `array`):

Leave out jobs whose title contains any of these words, such as "senior" or "manager".

## `onlyWithSalary` (type: `boolean`):

Leave out jobs that show no salary.

## `minYearlySalary` (type: `integer`):

Keep only jobs whose salary reaches this amount a year, in the currency of the jobs' country. Hourly, daily, weekly and monthly salaries are counted for a full-time year (2,080 hours). Jobs without a salary are left out when this is set.

## `includeSources` (type: `array`):

Keep only jobs published via these sites, such as LinkedIn or Indeed (the "via ..." line).

## `excludeSources` (type: `array`):

Leave out jobs published via these sites.

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

Language of Google's labels, as a Google language code such as en, es or de. Job texts stay in the language they were posted in.

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

Two-letter country code Google uses to localize results, such as us, gb, es or mx.

## `newJobsOnly` (type: `boolean`):

Store only jobs that earlier runs of the same monitor did not store, so a daily schedule gives you just the new postings. A job reposted on another site counts as already seen. The first run stores everything it finds.

## `monitorName` (type: `string`):

Optional. Runs with the same monitor name share their memory of seen jobs. Leave empty to name it after the searches, country and language, so each set of searches keeps its own memory.

## Actor input object example

```json
{
  "queries": [
    "software engineer jobs in Austin"
  ],
  "location": "",
  "maxJobsPerQuery": 20,
  "datePosted": "any",
  "employmentTypes": [],
  "remoteOnly": false,
  "noDegreeOnly": false,
  "excludeCompanies": [],
  "excludeTitleWords": [],
  "onlyWithSalary": false,
  "includeSources": [],
  "excludeSources": [],
  "language": "en",
  "country": "us",
  "newJobsOnly": false,
  "monitorName": ""
}
```

# 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 = {
    "queries": [
        "software engineer jobs in Austin"
    ]
};

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

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

```

## MCP server setup

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