# Glassdoor Scraper — Jobs, Salaries & Company Ratings (`tortuga/glassdoor-scraper`) Actor

Scrape Glassdoor jobs by keyword + location or URL on 7 country sites: title, company, rating, salary range (employer or estimate), remote, Easy Apply, posted date, description, company overview.

- **URL**: https://apify.com/tortuga/glassdoor-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 job scrapeds

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

## Glassdoor Scraper — Jobs, Salaries & Company Ratings

Scrape job listings from **Glassdoor** by keyword and location, with Glassdoor's own filters (date posted, job type,
remote, salary range, Easy Apply, company rating, seniority, distance), or from any Glassdoor job search URL. Works on
**glassdoor.com and six country sites**: United Kingdom (glassdoor.co.uk), Canada (glassdoor.ca), India
(glassdoor.co.in), Australia (glassdoor.com.au), Germany (glassdoor.de) and France (glassdoor.fr).

For every job you get the title, company with its Glassdoor rating and logo, location, remote / hybrid / on-site,
the **salary range** (min, median, max, pay period, currency) and **whether it is employer-provided or a Glassdoor
estimate**, job types, seniority, skills, the snippet, age and posting date, the **Easy Apply** flag and the job URL.
Optionally it adds the **full job description** and the **company overview** a logged-out visitor sees next to the
job: size, industry, sector, founded, revenue, headquarters, website, CEO, the ratings breakdown (culture, work-life
balance, compensation & benefits, career opportunities, senior management, CEO approval, recommend to a friend),
review count, **benefits rating** and review highlights.

No Glassdoor account, no cookies, no browser. Export to JSON, CSV, Excel or use the API.

### What data does the Glassdoor Scraper return?

| Field | Example | Notes |
|---|---|---|
| `jobId`, `url` | `1010289241386`, `https://www.glassdoor.com/job-listing/data-analyst-i-erib-goldbelt-JV_KO0,19_KE20,28.htm?jl=1010289241386` | Glassdoor's job listing id and public job page |
| `title`, `normalizedTitle` | `Data Analyst I (ERIB)`, `data analyst` | `normalizedTitle` = Glassdoor's standard job title |
| `company`, `companyId`, `companyRating`, `companyLogoUrl` | `Goldbelt, Inc.`, `977530`, `4`, `https://media.glassdoor.com/sql/977530/...png` | rating = Glassdoor overall rating (1-5) |
| `location`, `locationId`, `locationType` | `Massachusetts`, `3399`, `state` | city, state, metro or country |
| `isRemote`, `workplaceType` | `true`, `Remote` | Remote, Hybrid or On-site when the ad says so |
| `salaryText` | `$80K - $90K (Employer provided)` | as the job card shows it |
| `salaryMin`, `salaryMedian`, `salaryMax`, `salaryPeriod`, `salaryCurrency` | `80000`, `85000`, `90000`, `year`, `USD` | period: hour, day, week, month or year |
| `salarySource`, `isSalaryEstimate` | `employer`, `false` | `employer` (employer-provided) or `glassdoor_estimate` |
| `jobTypes`, `seniority` | `["Full-time"]`, `Entry level` | labels in the site's language |
| `skills`, `attributes` | `["Statistics", "SAS"]`, `["Databricks", "Bachelor's degree"]` | skills and other requirements / benefits Glassdoor extracted from the ad |
| `snippet` | `Knowledge of the principles, methods...` | short extract of the ad |
| `ageInDays`, `postedAgo`, `postedDate` | `2`, `2d`, `2026-10-09` | `postedDate` = scrape date minus age |
| `easyApply`, `sponsored` | `false`, `false` | Easy Apply = apply on Glassdoor |
| `searchKeyword`, `searchLocation`, `searchUrl`, `site`, `position`, `scrapedAt`, `detailsFetched` | | where and when the job was found |
| `description`, `descriptionHtml`, `postedAt` | `Overview: Goldbelt Professional Services...`, `2026-10-08T00:00:00Z` | with **Include full job description** |
| `city`, `state`, `countryName`, `latitude`, `longitude` | `Englewood, NJ`, `New Jersey`, `United States`, `40.89278`, `-73.97306` | with details; coordinates for city-level jobs |
| `companyName`, `companyWebsite`, `companySize`, `companyType`, `companyIndustry`, `companySector`, `companyFounded`, `companyRevenue`, `companyHeadquarters`, `companyCeo` | `Goldbelt, Inc`, `https://www.goldbelt.com/careers/`, `1001 to 5000 Employees`, `Company - Private`, `Staffing & Subcontracting`, `Human Resources & Staffing`, `1974`, `$100 to $500 million (USD)`, `Juneau, AK`, `McHugh Pierre` | with details, when the company has a Glassdoor profile |
| `companyRatings` | `{"overall": 4, "workLifeBalance": 4.1, "ceoApprovalPercent": 82, "recommendToFriendPercent": 71, ...}` | with details |
| `companyReviewCount`, `benefitsRating`, `benefitsReviewCount`, `benefitsHighlights`, `reviewHighlights` | `25`, `4.1`, `25`, `["401K Plan", "Health Insurance"]`, `[{"text": "Great pay but...", "sentiment": "positive"}]` | with details |
| `companyOverviewUrl`, `companyReviewsUrl`, `companySalariesUrl`, `companyBenefitsUrl`, `isExpired` | | with details |

### How to scrape Glassdoor jobs by keyword and location

1. Enter one or more **Keywords** (job title, skill or company) and a **Location** such as `New York, NY`, `London`,
   `Texas` or `Germany`. Glassdoor's own location suggestions pick the place. Leave the location empty to search the
   whole country of the selected site.
2. Pick the **Glassdoor site** (US, UK, Canada, India, Australia, Germany, France).
3. Optionally set filters: date posted, job type, remote only, minimum / maximum salary, Easy Apply only, minimum
   company rating, seniority, distance.
4. Set **Max jobs** and run.

```json
{
  "keywords": ["data analyst", "business analyst"],
  "location": "Chicago, IL",
  "country": "US",
  "datePosted": "7",
  "jobType": "fulltime",
  "minSalary": 70000,
  "maxItems": 500
}
```

You can also paste Glassdoor URLs into **Start URLs**: search pages with any filters you set on the site (on any of
the seven sites) and single job pages, which always come with full details:

```json
{
  "startUrls": [
    { "url": "https://www.glassdoor.com/Job/new-york-ny-software-engineer-jobs-SRCH_IL.0,11_IC1132348_KO12,29.htm?fromAge=3&applicationType=1" },
    { "url": "https://www.glassdoor.co.uk/Job/london-software-engineer-jobs-SRCH_IL.0,6_IC2671300_KO7,24.htm" },
    { "url": "https://www.glassdoor.com/job-listing/ms-now-wordpress-web-engineer-tavant-JV_IC1126752_KO0,29_KE30,36.htm?jl=1010276908880" }
  ],
  "maxItems": 300
}
```

#### Output example

```json
{
  "jobId": "1010289241386",
  "url": "https://www.glassdoor.com/job-listing/data-analyst-i-erib-goldbelt-JV_KO0,19_KE20,28.htm?jl=1010289241386",
  "title": "Data Analyst I (ERIB)",
  "company": "Goldbelt, Inc.",
  "companyId": 977530,
  "companyRating": 4,
  "location": "Massachusetts",
  "locationType": "state",
  "isRemote": true,
  "workplaceType": "Remote",
  "salaryText": "$80K - $90K (Employer provided)",
  "salaryMin": 80000,
  "salaryMax": 90000,
  "salaryMedian": 85000,
  "salaryPeriod": "year",
  "salaryCurrency": "USD",
  "salarySource": "employer",
  "isSalaryEstimate": false,
  "jobTypes": ["Full-time"],
  "seniority": "Entry level",
  "skills": ["Statistics", "Microsoft Excel", "SAS", "Spark"],
  "ageInDays": 2,
  "postedAgo": "2d",
  "postedDate": "2026-10-09",
  "easyApply": false,
  "sponsored": false,
  "detailsFetched": true,
  "description": "Overview:\n\nGoldbelt Professional Services specializes in providing expert resources for Public Health missions...",
  "companySize": "1001 to 5000 Employees",
  "companyIndustry": "Staffing & Subcontracting",
  "companyFounded": 1974,
  "companyRevenue": "$100 to $500 million (USD)",
  "companyHeadquarters": "Juneau, AK",
  "companyRatings": {"overall": 4, "cultureAndValues": 3.6, "workLifeBalance": 4.1, "compensationAndBenefits": 3.8,
                     "careerOpportunities": 3.5, "seniorManagement": 3.6, "ceoApprovalPercent": 82,
                     "recommendToFriendPercent": 71},
  "benefitsRating": 4.1,
  "companyReviewCount": 25
}
```

### How many jobs can I get per search?

Glassdoor shows at most **30 pages of 30 jobs (900) for any one search**; asking for page 31 returns an error. When a
search lists more and you ask for more, **Collect more than Glassdoor's 900 jobs per search** (on by default) reads
the same search from other entry points: oldest first, oldest first within "posted in the last 14 / 30 days", then
per job category, job type or seniority bucket (Glassdoor's own filter counts), each of those again from both ends.
Repeated jobs are dropped and never charged. In a test, "registered nurse" in Chicago (2,273 jobs listed) returned
1,500 distinct jobs (the run's limit) from 187 requests; "software engineer" in New York (3,568 listed) returned
1,944. Very large searches are not fully reachable: split them yourself by city or filter for complete coverage.

Results come in Glassdoor's **"Most recent"** order by default. Glassdoor's "relevance" order mixes in sponsored ads
that repeat on later pages (only about 45% distinct jobs over 30 pages in our tests), while the date order repeats
far less (about 86% distinct).

### Can I get the full job description and company details?

Yes. Turn on **Include full job description and company details**. For each job the actor asks Glassdoor for the job's
details (one extra request, about 18 KB) and adds the full description (text and HTML), the date Glassdoor found the
ad, coordinates, and the company box a logged-out visitor sees: size, type, industry, sector, founded, revenue,
headquarters, website, CEO, ratings breakdown, number of reviews, benefits rating with highlights, and review
highlights. Job URLs in Start URLs always come with details. Company reviews and interview pages themselves are not
scraped: Glassdoor puts them behind a login after a few, and its review pages refused all our test requests.

### Which Glassdoor sites are supported? Does it work without login?

glassdoor.com (US), glassdoor.co.uk, glassdoor.ca, glassdoor.co.in, glassdoor.com.au, glassdoor.de and glassdoor.fr;
salaries come in the site's currency and job type / company size labels in its language. Glassdoor.com searches can
use locations anywhere (e.g. `London` or `Berlin`).

No login or cookies are needed: the actor asks Glassdoor's public job search the same questions its website asks when
you page through results. Glassdoor is protected by Cloudflare; Apify **RESIDENTIAL** proxy (the default) passed 99%
of search requests on the first try in our tests. Datacenter IPs are mostly blocked; if they are, the actor switches
to residential IPs by itself.

### Monitor changes on a schedule

Turn on **Only new or changed items** to watch a search: each run remembers what earlier runs returned and outputs
only jobs that are new or whose title or salary range changed. Unchanged jobs are dropped before any details request,
so they are not charged. **Max jobs** then sets how many of the most recent jobs are checked per run. Save the input as a
task and add a Schedule in Apify (for example daily); give each watch its own **Monitoring key** if several schedules
use the same search. Every output item has `changeType` (`new` or `changed`), and changed jobs have `previousValues`
with the old values, e.g. `{"salaryMax": 110000}`.

### Pricing

Pay per job: **$0.0003 per job** ($0.30 per 1,000). With **Include full job description and company details** (or for
a job URL) each job adds a **$0.0001 detail** event, so $0.40 per 1,000 jobs with descriptions and company data. No
start fee and no subscription.

### Proxy note and cost

You also pay Apify platform usage for your runs, mainly residential proxy traffic: about 25 KB per page of 30 jobs
and about 6 KB per job with details. In our tests that was **about $0.03 per 1,000 jobs** without details (proxy plus
compute). Detail requests are more often challenged and retried, so details add roughly $0.05-0.20 per 1,000 jobs.
Using your own proxy or Apify datacenter proxy is possible but Glassdoor blocks most datacenter IPs.

### Is it legal to scrape Glassdoor?

The actor collects only what Glassdoor shows publicly to logged-out visitors: job ads, company names and public
company information, salary ranges and aggregate ratings. It does not log in, does not open review or interview
pages behind the login wall and collects no personal data of job seekers. Job ads can contain the names of
recruiters or contact persons written into the description by the employer. Check Glassdoor's terms of use and the
data protection rules that apply to you before using the data, especially for commercial purposes.

# Actor input Schema

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

One Glassdoor job search per keyword, e.g. "software engineer" or "registered nurse". Combine with Location and the filters below. Leave empty when you use Start URLs.

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

City, state, metro area or country as you would type it on Glassdoor, e.g. "New York, NY", "London", "Texas". Glassdoor's own location suggestions pick the place. Empty = the whole country of the selected Glassdoor site.

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

Which Glassdoor country site to search. Each site lists its own country's jobs, salaries in local currency.

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

Glassdoor job search URLs with any filters set on the site, e.g. https://www.glassdoor.com/Job/new-york-ny-software-engineer-jobs-SRCH_IL.0,11_IC1132348_KO12,29.htm?fromAge=7 (any country site), or job URLs (/job-listing/...htm?jl=123). Job URLs always include the full details.

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

Only jobs posted within this period.

## `jobType` (type: `string`):

Glassdoor's job type filter.

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

Only jobs Glassdoor marks as remote / work from home.

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

Only jobs whose pay range (employer-provided or Glassdoor estimate) reaches at least this yearly amount, in the site's currency, e.g. 100000.

## `maxSalary` (type: `integer`):

Only jobs whose pay range starts below this yearly amount, in the site's currency.

## `easyApplyOnly` (type: `boolean`):

Only jobs you can apply to on Glassdoor directly.

## `minRating` (type: `string`):

Only jobs at companies rated at least this on Glassdoor.

## `seniority` (type: `string`):

Glassdoor's seniority filter.

## `sort` (type: `string`):

Most recent first (default) or Glassdoor's relevance order. Relevance mixes in sponsored ads that repeat on later pages, so deep searches return fewer distinct jobs. Also applied to start URLs that have no sort of their own.

## `radius` (type: `string`):

Search radius around a city (miles on glassdoor.com, km on most other sites). Default = the site's default (25 miles / 50 km).

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

Stop after this many jobs in total (all searches together). You pay per job saved.

## `maxItemsPerSearch` (type: `integer`):

Optional cap for each keyword / start URL, so one broad search does not use up Max jobs.

## `splitLargeSearches` (type: `boolean`):

Glassdoor shows at most 30 pages (900 jobs) of any search. When a search has more and Max jobs asks for more, re-run it per job category, then per seniority / job type, to reach jobs beyond the first 900.

## `includeDetails` (type: `boolean`):

One extra request per job: full description, job types, exact coordinates, company size, industry, founded, revenue, HQ, website, ratings breakdown, benefits rating and review highlights. Charged as an extra 'detail' event per job.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. For jobs: new job ads, or ads whose title or salary range changed.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

Glassdoor blocks most datacenter IPs, so Apify RESIDENTIAL proxy is the default (about 10-15 KB of traffic per 30 jobs, ~6 KB per job with details). A blocked datacenter proxy switches to RESIDENTIAL automatically.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "location": "New York, NY",
  "country": "US",
  "sort": "date",
  "maxItems": 100,
  "splitLargeSearches": true,
  "includeDetails": false,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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"
    ],
    "location": "New York, NY",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/glassdoor-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"],
    "location": "New York, NY",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/glassdoor-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"
  ],
  "location": "New York, NY",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call tortuga/glassdoor-scraper --silent --output-dataset

```

## MCP server setup

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