# Glassdoor Jobs Scraper - Salaries, Ratings & Reviews (`zyra/glassdoor-jobs-scraper`) Actor

Every Glassdoor job listing with the employer's reputation attached: pay estimates, apply link, company rating, size, revenue, CEO approval, plus culture and work/life scores and employee pros and cons. 40 fields per job, from any Glassdoor search URL.

- **URL**: https://apify.com/zyra/glassdoor-jobs-scraper.md
- **Developed by:** [Zyra](https://apify.com/zyra) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$2.00 / 1,000 job listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Glassdoor Jobs Scraper

**Every job listing, with the employer's full reputation attached.**

Most job scrapers hand you a title, a location and a link. This one hands you
the job *and* the company behind it — ratings, salary bands, benefits, revenue,
leadership approval, and what people doing that exact role say about working
there. Forty fields per listing, in one clean row, ready for analysis.

Search on Glassdoor exactly as you normally would. Paste the URL. Get
structured data.

### Why this one

**The company comes with the job.** No second scrape, no matching step, no
joining two datasets on a fuzzy company name. Each row already carries the
employer's rating, size, sector, revenue, headquarters and CEO approval score.

**Salary bands, where Glassdoor publishes them.** The employer's estimated
range with its median, pay type and currency — and, on listings where Glassdoor
has its own estimate, that too, so you can compare the two.

**Sentiment from the same role.** Listings often carry pros and cons written by
people in that job at that company, plus employee benefit reviews. That is
qualitative context most job data simply does not have.

**Your search, your filters.** Role, location, salary band, date posted,
remote — whatever you set on Glassdoor is respected. If the search works in
your browser, it works here.

### What you get

**The job** — title, location, full job overview, direct application link,
posting ID, and the canonical listing URL.

**The pay** — the employer's estimated range and median, pay type and
currency, plus Glassdoor's own estimate and median where it publishes one.

**The company** — name, ID, rating, size, industry, sector, type, revenue,
headquarters, founded year, website, CEO, plus the percentage of employees who
approve of the CEO and who would recommend the company to a friend.

**The employee verdict** — separate ratings for culture and values, career
opportunities, compensation and benefits, senior management, and work/life
balance, alongside a benefits summary, benefit reviews, and pros and cons from
people in the same role.

### Sample output

One real row, abridged:

```json
{
  "job_title": "Senior Engineer - Safety & Multimedia / Audio & Camera (iRDK)",
  "job_location": "Santa Clara, CA",
  "job_posting_id": "1010233743600",
  "job_application_link": "https://www.glassdoor.com/partner/jobListing.htm?pos=101...",

  "pay_range_Employer_est": "68911 - 161544",
  "pay_median_employer": 115228,
  "pay_range_currency": "USD",
  "pay_type": "ANNUAL",

  "company_name": "Capgemini",
  "company_rating": 4.1,
  "company_size": "10000+ Employees",
  "company_industry": "Enterprise Software & Network Solutions",
  "company_sector": "Information Technology",
  "company_revenue": "$10+ billion (USD)",
  "company_headquarters": "Issy-les-Moulineaux, France",
  "company_founded_year": 1967,
  "company_ceo": "Aiman Ezzat",
  "percentage_that_approve_of_ceo": 0.69,
  "percentage_that_recommend_company_to_a friend": 0.88,

  "company_culture_and_values_rating": 4.2,
  "company_work/life_balance_rating": 4.2,
  "company_career_opportunities_rating": 4.1,
  "company_comp_and_benefits_rating": 3.8,
  "company_senior_management_rating": 3.9,

  "reviews_by_same_job_pros": ["Good infrastructure and work culture", "..."],
  "reviews_by_same_job_cons": ["Low salaries and slow promotions", "..."],
  "employee_benefit_reviews": ["Cigna insurance which is great", "Good 401k", "..."]
}
```

Every field above came from a single row of a live run. Export to JSON, CSV,
Excel or XML, or pull it straight from the API.

#### How completely listings are filled in

Glassdoor does not publish every field for every job, so neither does this. From
a 25-listing sample run:

| Field group | Present on |
| --- | --- |
| Job title, location, apply link, company name, overall company rating | ~100% |
| Pay type and currency | ~92% |
| Employer pay range and median | ~72% |
| Company ratings — culture, management, work/life, career, comp | ~68% |
| Employee benefit reviews | ~60% |
| Pros and cons from the same role | ~56% |
| Glassdoor's own pay estimate | ~20% |

Rates vary by search: well-known employers are documented far more fully than
small ones. Fields Glassdoor has no data for come back empty rather than
guessed at.

### How it works

1. Search jobs on Glassdoor and copy the URL from your address bar.
2. Paste it into **Glassdoor search URLs**. Add more URLs to run several
   searches at once.
3. Set a limit if you want one, and run it.

### Input

| Field | Required | What it does |
| --- | --- | --- |
| **Glassdoor search URLs** | yes | One or more Glassdoor jobs search or listing URLs. Every job behind each one is collected. |
| **Max jobs per URL** | no | Stop after this many jobs from each search. **Prefilled at 10**, so a first run is a quick sample. Raise it up to 1,000 for a full collection, or clear the field to collect 1,000 per URL. |
| **Max jobs in total** | no | Stop the whole run after this many jobs, across all searches. Up to 10,000; empty means 10,000. |

Both limits are applied *during* collection rather than to the results
afterwards, so a limited run genuinely does less work and finishes sooner. Every
run is bounded, so a broad search can never run away with itself.

**Run it once to see the shape of the data, then open it up.** The prefilled 10
jobs per URL keeps a first run quick and cheap; raise **Max jobs per URL** when
you know the search is the one you want.

### Built to be trusted with real work

**Stop a run at any time and keep what it found.** Aborting stops the
collection and delivers every listing completed up to that moment. Nothing is
abandoned and nothing half-fetched is passed off as a result.

**You are never charged for a job you did not receive.** Listings that failed
to fetch are reported separately and never reach your dataset.

**Runs are self-limiting.** Time budgets scale with the size of the request, so
a bigger job simply gets longer rather than being cut off at an arbitrary
number.

**Clean, stable output.** Field names come straight from the source schema and
are not renamed or reshaped between runs, so whatever you build on top of this
keeps working.

**No invented data.** A field Glassdoor does not publish comes back empty.
Nothing is inferred, averaged or filled in to make a row look complete.

### What people use it for

- **Recruiting intelligence** — track who is hiring, for what, where, and at
  what pay, with employer reputation attached.
- **Compensation benchmarking** — compare Glassdoor and employer salary
  estimates across companies, roles and locations.
- **Employer brand research** — pair open roles with culture, management and
  work/life ratings to see how companies are actually perceived.
- **Market and competitor analysis** — watch hiring signals as a leading
  indicator of where a company is investing.
- **Lead generation** — find companies hiring for roles that indicate they need
  what you sell.

### Free accounts

On a free Apify plan a run collects up to 10 job listings, whatever the limits
above say. Nothing beyond that is collected, so a capped run finishes quickly.
Upgrade to a paid plan and the limits above apply in full.

### Good to know

- A search URL is checked for shape, not for results. Whether a search returns
  any jobs is not knowable until collection runs.
- Repeated search URLs are collected once, so a duplicate never costs twice.
- How long a run waits is worked out from how many jobs it could collect — both
  limits and the number of search URLs. A bigger request gets longer. There is
  no setting to guess at.
- If a search cannot be crawled, it is reported in the log and counted in the
  run summary rather than silently dropped.

# Actor input Schema

## `searchUrls` (type: `array`):

One or more Glassdoor jobs search or listing URLs. Every job found behind each URL is collected. Paste the URL straight from the address bar after searching on Glassdoor — the filters already on it (role, location, salary, date posted) are kept.

## `maxJobsPerUrl` (type: `integer`):

Stop after this many jobs from each search URL. Prefilled at 10 so a first run is a quick sample; raise it for a full collection, up to 1,000. Clearing the field collects up to 1,000 per URL.

## `maxJobsTotal` (type: `integer`):

Stop the whole run after this many jobs, across all search URLs together. Leave empty for the maximum of 10,000.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.glassdoor.com/Job/united-states-software-engineer-jobs-SRCH_IL.0,13_IN1_KO14,31.htm"
  ],
  "maxJobsPerUrl": 10,
  "maxJobsTotal": 10000
}
```

# Actor output Schema

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

Every job listing collected, one item per job with its company attached.

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

What was requested, what arrived, and the collection id to resume from if the run stopped waiting.

# 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 = {
    "searchUrls": [
        "https://www.glassdoor.com/Job/united-states-software-engineer-jobs-SRCH_IL.0,13_IN1_KO14,31.htm"
    ],
    "maxJobsPerUrl": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("zyra/glassdoor-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 = {
    "searchUrls": ["https://www.glassdoor.com/Job/united-states-software-engineer-jobs-SRCH_IL.0,13_IN1_KO14,31.htm"],
    "maxJobsPerUrl": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("zyra/glassdoor-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 '{
  "searchUrls": [
    "https://www.glassdoor.com/Job/united-states-software-engineer-jobs-SRCH_IL.0,13_IN1_KO14,31.htm"
  ],
  "maxJobsPerUrl": 10
}' |
apify call zyra/glassdoor-jobs-scraper --silent --output-dataset

```

## MCP server setup

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