# Glassdoor Jobs Scraper & New Job Monitor - Pay Range & Ratings (`neverempty/glassdoor-jobs-monitor`) Actor

For recruiters, staffing agencies and job seekers: Glassdoor jobs by search term and place with company, rating, pay range, remote/hybrid tags, days since posted and link. Pay range was on 95% of 222 jobs checked on 2026-10-10. Jobs found twice are charged once; watch mode returns only new jobs.

- **URL**: https://apify.com/neverempty/glassdoor-jobs-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 75.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.60 / 1,000 job returneds

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

## Glassdoor Jobs Scraper & New Job Monitor

**Glassdoor job alerts and job data with pay ranges and company ratings.** Get job listings from **Glassdoor's public job search** by search term and place (country, or any city you pick on glassdoor.com), with filters for posting date, remote, job type, pay and company rating. One row per job: title, company, company rating, location, remote / hybrid / in-person tags, job types, pay range with currency, period and source (employer-provided or Glassdoor estimate), days since posted, Easy Apply, a short description and the job link. **Watch mode** turns a search into a feed: run it on a schedule and each run returns only the jobs posted since the watch started that you have not received yet.

No Glassdoor account, cookies or API key needed. Run up to 20 searches at once: the same job found by two searches is returned and charged once. Export as JSON, CSV or Excel, or push new jobs to Slack, email or a sheet with an Apify integration.

### What you can do with it

- **Recruiters and staffing agencies**: watch `registered nurse` in Texas or `software engineer` in New York every morning and get only the new openings, with the hiring company and its rating, then push them to Slack, email or a sheet with an Apify integration.
- **Job seekers**: remote data analyst jobs posted in the last 3 days at companies rated 4 stars or more, paying at least $90,000 a year.
- **Market research**: how many jobs Glassdoor lists for a title and place (`jobsInSearch`), which companies are hiring, pay ranges and how often they are employer-provided or estimated.

### Input

| Field | What it does |
|---|---|
| `searchQueries` | Job titles or keywords, one per line: `data analyst`, `registered nurse`, `software engineer`. |
| `country` | Country for the search terms: United States (default), United Kingdom, Canada, India, Australia, Germany, France. |
| `searchUrls` | Or paste a Glassdoor job search address for any city or region, such as `https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm`. Choose the place in Glassdoor's own search box, then copy the address. The filters `fromAge`, `remoteWorkType`, `jobTypeIndeed`, `minSalary`, `minRating` and `applicationType` in the address are kept. |
| `postedWithinDays` | 1, 3, 7, 14 or 30. |
| `remoteOnly` | Only jobs tagged Remote. |
| `jobType` | `full-time`, `part-time`, `contract`, `permanent` or `temp-to-hire`. |
| `minSalary` | Minimum pay per year in the search's currency (hourly pay counts as 2,080 hours a year). |
| `minCompanyRating` | 1 to 4 (stars and up). |
| `easyApplyOnly` | Only Easy Apply jobs. |
| `maxResultsPerSearch` | Jobs per search, 1 to 30 (default 30). |
| `onlyNew` | Watch mode (see below). |
| `watchName` | Keeps separate memories for separate schedules of the same search. |
| `resetMonitoringState` | Start a watch over. |

Example: `{ "searchQueries": ["data analyst"], "country": "United States", "postedWithinDays": "3" }`

### Output

One row per job (`status: "ok"`):

| Column | Meaning |
|---|---|
| `jobId` | Glassdoor's job listing ID. |
| `title`, `company`, `companyRating` | Job title; company name as Glassdoor shows it on the job card; the company's Glassdoor rating (1 to 5, `null` when the company has none). |
| `companyNameInListing` | The employer name written in the listing itself (can be the legal name, such as "Dillard's, Inc." for the card name "Dillard's"). |
| `location`, `locationType` | Place as Glassdoor shows it (`New York, NY`, `United States` for remote jobs) and its kind (`city`, `state`, `country`). |
| `workSetting` | Tags Glassdoor gives the job: `Remote`, `Hybrid`, `In-person`. Empty when the job has no such tag (not "in-person"). |
| `jobTypes`, `experienceLevels` | Tags such as `Full-time`, `Contract`, `Part-time`; `Entry level`, `Mid-level`, `Senior level`. |
| `payLow`, `payMedian`, `payHigh`, `payCurrency`, `payPeriod` | The pay range shown on the job card and its unit (`year`, `hour`, `month`…). `null` when Glassdoor shows no pay — never 0. |
| `paySource` | `employer` (Employer provided) or `glassdoor-estimate` (Glassdoor est.). |
| `ageInDays`, `postedDateApprox` | Days since posted, as Glassdoor shows it, and the date that gives (approximate, day precision). |
| `easyApply`, `isSponsored` | Easy Apply job; sponsored placement on the search page. |
| `normalizedTitle`, `descriptionSnippet`, `attributes` | Glassdoor's standard title, the short description shown on the card, and the skill / benefit / schedule tags Glassdoor extracted from the listing. |
| `url` | The job's page on Glassdoor. |
| `positionInSearch`, `jobsInSearch` | Place on the search page and how many jobs Glassdoor lists for the search. |
| `changeType` | Watch mode only: `first-check` or `new`. |

Measured on 222 real jobs from 8 searches (United States and United Kingdom, 2026-10-10): pay range 95%, company rating 89%, job type tag 77%, experience level tag 86%, remote/hybrid/in-person tag 44%, job link 100%.

Searches that return nothing come back as one **free** row with a reason in `note` (`no-results`, `no-new-jobs`, `not-found`, `blocked`, `login-required`, `unreadable`, `more-need-login`, `budget-reached`, `bad-input`).

### Covering a whole market in one run

Put up to **20 searches in one run**: several places, several job titles, or the same title split by `postedWithinDays`, `jobType` or `remoteOnly`. The same job found by two searches is returned and charged **once**. Each row also says how many jobs the search has in total on Glassdoor, so you can see where to split further. With `postedWithinDays: 1` or `3`, each search holds the freshest jobs.

### Watch mode

Turn on `onlyNew` and schedule the same input (for example every morning):

1. The first run returns the current jobs (`changeType: "first-check"`) and remembers them.
2. Later runs return only jobs **posted from the day the watch started** that were not returned before (`changeType: "new"`). Older jobs that move into the first page later are not called new.
3. When nothing is new, you get one free `no-new-jobs` row.

The memory is per search and per `watchName`. A job that could not be returned (for example because the run hit its maximum charge) is not marked as sent and comes back in the next run.

### Pricing

Pay per event: `job-returned` for each job row. In watch mode, a search that returns nothing new is charged one `search-checked` event. Free rows that say why something was not returned are never charged.

### Filters are checked on every row

Glassdoor's own filters are not always exact (on a real "4.0+ rating" page, 6 of 30 companies were rated 3.9). This Actor checks every returned job against the filters you set — date, remote tag, job type tag, pay, rating, Easy Apply — and leaves out the ones that do not match. It also checks that Glassdoor answered for the place and filters you asked for; when it does not know a place it falls back to the whole United States, and this Actor then returns a free `not-found` row instead of a different list.

### Notes

- Glassdoor shows signed-out visitors the first 30 jobs of a search, so each search returns up to 30 jobs (split the search as above to get more). The order is Glassdoor's own relevance order; sorting pages are not requested because Glassdoor's robots.txt asks crawlers not to.
- Unofficial and not affiliated with Glassdoor. Only public job search pages are read, as a signed-out visitor sees them. No login, no check pages solved, nothing behind the sign-in prompt.
- No personal data: the rows hold job and company information only.
- Glassdoor may change its pages; if a page cannot be read, you get a free `unreadable` row and nothing is charged.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `searchQueries` (type: `array`):

Job titles or keywords to search on Glassdoor, one per line (data analyst, registered nurse, "software engineer"). Each term is one search in the country chosen below. If this and the URLs below are both empty, the example data analyst (United States) is searched.

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

Country for the search terms above. For a city or region, open the search on glassdoor.com, choose the place there and paste the page address into Glassdoor search URLs instead. Empty means United States.

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

Or paste the address of a Glassdoor job search, such as https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm (any city or region). The filters fromAge, remoteWorkType, jobTypeIndeed, minSalary, minRating and applicationType in the address are kept and checked on every job; addresses with other filters (such as sorting) are refused.

## `postedWithinDays` (type: `string`):

Only jobs Glassdoor shows as posted within this many days: 1, 3, 7, 14 or 30. Empty means any date. Works well with watch mode on busy searches.

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

Only jobs Glassdoor tags as remote. Each returned job is checked for the Remote tag. Off means remote, hybrid and in-person jobs.

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

Only jobs Glassdoor tags with this employment type. Each returned job is checked for the tag. Empty or any means all types.

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

Only jobs whose shown pay range reaches at least this amount per year, in the local currency of the search (hourly pay counts as 2,080 hours a year). Jobs without a shown pay range are left out when this is set. Empty means no pay filter.

## `minCompanyRating` (type: `string`):

Only jobs at companies with at least this Glassdoor rating (1 to 4 stars and up). Jobs from companies without a rating are left out when this is set. Empty means any rating.

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

Only jobs you can apply to with Glassdoor's Easy Apply. Off means all jobs.

## `maxResultsPerSearch` (type: `integer`):

Most jobs to return from each search, 1 to 30. Glassdoor shows signed-out visitors the first 30 jobs of a search, and this Actor never signs in. Empty means 30.

## `onlyNew` (type: `boolean`):

On: the first run returns the current jobs and remembers them; later runs with the same searches return only jobs posted from the day the watch started that were not returned before. Run it on a schedule. Off: every run returns the current list.

## `watchName` (type: `string`):

Optional label to keep separate watches apart (letters, digits, dot, dash, underscore; up to 40). Empty uses one shared default watch.

## `resetMonitoringState` (type: `boolean`):

On: forget what this watch has seen and treat this run as its first check. Off: keep the watch's memory.

## Actor input object example

```json
{
  "searchQueries": [
    "data analyst"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Glassdoor job listing: job ID, title, company, company rating, location, remote/hybrid/in-person tags, job types, pay range with currency, period and source (employer or Glassdoor estimate), days since posted, Easy Apply, short description and job link. Watch mode marks rows first-check or new. A search with no jobs, nothing new, a check page, a sign-in page or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "searchQueries": [
        "data analyst"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/glassdoor-jobs-monitor").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 = { "searchQueries": ["data analyst"] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/glassdoor-jobs-monitor").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 '{
  "searchQueries": [
    "data analyst"
  ]
}' |
apify call neverempty/glassdoor-jobs-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/glassdoor-jobs-monitor"
        }
    }
}
```

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/S1iGWdu8a0CHSxsAt/builds/1JMxMVKejl17oYHjx/openapi.json
