# Glassdoor Jobs & Salary Scraper — percentile pay, normalized (`entrogix_works/glassdoor-jobs-salary-scraper`) Actor

Scrape Glassdoor job search results with p10/p50/p90 salary estimates normalized to annual figures. Unofficial; not affiliated with Glassdoor.

- **URL**: https://apify.com/entrogix\_works/glassdoor-jobs-salary-scraper.md
- **Developed by:** [Entrogix Works](https://apify.com/entrogix_works) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 91.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 job scrapeds

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/platform/actors/running/actors-in-store#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 & Salary Scraper — percentile pay, normalized

Paste a Glassdoor search URL and get back structured job listings **with Glassdoor's p10 / p50 / p90 salary estimates converted to comparable annual figures**.

Glassdoor publishes a pay *range with percentiles*, not a single number — but it mixes hourly and annual rates in the same result set, so you cannot sort or compare them as they come. This Actor normalizes everything to an annual basis and keeps the percentile shape intact.

### What you get per job

| Field | Example |
|---|---|
| `title`, `company`, `location` | `Web Analytics Analyst`, `Ralph Lauren`, `New York, NY` |
| `annualP10` / `annualMid` / `annualP90` | `62400` / `78100` / `95000` |
| `payPeriod`, `annualBasis` | `ANNUAL` / `HOURLY` — the original unit is always reported |
| `ageInDays`, `easyApply`, `isSponsored` | `30`, `false`, `false` |
| `normalizedTitle`, `url` | Glassdoor's own job-title normalization, plus a direct link |

An hourly listing at `$34.05/hr` becomes `annualMid: 70824` (× 2080 h), sitting directly comparable next to a salaried role — and `annualBasis` tells you it was converted, so nothing is hidden.

### Summary (key-value store, `SALARY_SUMMARY`)

`totalJobs`, `jobsWithSalary`, **`salaryDisclosureRate`**, `annualP25`, `annualMedian`, `annualP75`, `currency`.

The disclosure rate matters: listings that publish pay skew toward better-paying employers, so a median computed without knowing the denominator is inflated. This Actor always tells you how much of the sample it is based on.

### Input

```json
{
  "searchUrls": [
    "https://www.glassdoor.com/Job/new-york-data-analyst-jobs-SRCH_IL.0,8_IC1132348_KO9,21.htm"
  ],
  "maxItemsPerUrl": 50
}
```

**Why a URL instead of keywords?** Glassdoor search URLs embed internal location and occupation IDs (`SRCH_IL.0,8_IC1132348_KO9,21`) that cannot be derived from a keyword. Rather than guess and quietly return the wrong city, this Actor asks you to paste the search you actually want. Run the search in your browser, copy the address bar, paste it here.

### Scope and limits

- Reads **public job search result pages only**. No login, no private data.
- Returns roughly **30 jobs per URL** — that is one Glassdoor result page. Pagination is JavaScript-driven and this Actor does not simulate scrolling, so raising `maxItemsPerUrl` beyond that will not produce more. To collect a larger sample, pass several search URLs (different pages or cities).
- Requires a **residential proxy**. Glassdoor blocks datacenter IPs.

### Pricing

Pay per result — you are charged only for jobs actually delivered to your dataset. Duplicates are removed **before** charging.

### Disclaimer

**This is an unofficial tool and is not affiliated with, endorsed by, or sponsored by Glassdoor.** "Glassdoor" is a trademark of its respective owner and is used here only to describe what this Actor reads. Salary figures are Glassdoor's own estimates, not verified compensation data. You are responsible for ensuring your use of the collected data complies with applicable law and with Glassdoor's terms.

# Actor input Schema

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

Paste the URL of a Glassdoor job search results page (the one containing /Job/). Glassdoor search URLs embed internal IDs and cannot be built from keywords, so this Actor asks for the real URL instead of guessing.

## `maxItemsPerUrl` (type: `integer`):

Glassdoor returns about 30 jobs per page. Higher values will not produce more.

## `minIntervalMs` (type: `integer`):

Politeness delay.

## `useProxy` (type: `boolean`):

Off by default — this target was measured to work 5/5 without a proxy. Turn on only if you hit blocks.

## `proxyType` (type: `string`):

Used only when Use Apify Proxy is on. DATACENTER costs far less than RESIDENTIAL.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.glassdoor.com/Job/new-york-data-analyst-jobs-SRCH_IL.0,8_IC1132348_KO9,21.htm"
  ],
  "maxItemsPerUrl": 50,
  "minIntervalMs": 3000,
  "useProxy": false,
  "proxyType": "DATACENTER"
}
```

# 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/new-york-data-analyst-jobs-SRCH_IL.0,8_IC1132348_KO9,21.htm"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("entrogix_works/glassdoor-jobs-salary-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/new-york-data-analyst-jobs-SRCH_IL.0,8_IC1132348_KO9,21.htm"] }

# Run the Actor and wait for it to finish
run = client.actor("entrogix_works/glassdoor-jobs-salary-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/new-york-data-analyst-jobs-SRCH_IL.0,8_IC1132348_KO9,21.htm"
  ]
}' |
apify call entrogix_works/glassdoor-jobs-salary-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,entrogix_works/glassdoor-jobs-salary-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/YHA4Sz0YZ9he8VmOZ/builds/81lFlTN35y1GntTDe/openapi.json
