# Glassdoor Jobs Scraper (`skootle/glassdoor-jobs-reviews`) Actor

Scrape Glassdoor job listings with numeric salary range (USD), employer rating, ISO posted date, employment type, and experience level. Stable record IDs for daily watchlist dedupe. Drop-into-LLM summary card per record. Export, run via API, schedule, or integrate with other tools.

- **URL**: https://apify.com/skootle/glassdoor-jobs-reviews.md
- **Developed by:** [Skootle](https://apify.com/skootle) (community)
- **Categories:** Jobs, AI, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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](https://raw.githubusercontent.com/kesjam/skootle-actors-assets/main/heroes/glassdoor-jobs-reviews.png)

### TL;DR

Pull every Glassdoor job listing for a search you'd run by hand: title, company, location, **numeric salary range**, employer rating, posted date, employment type, experience level. Returns ~30 jobs per page of any Glassdoor search URL, normalized to a stable schema with ISO 8601 dates and typed enums. Built for recruiters sourcing engineers in their metro, lead-gen agencies building outreach lists, salary-benchmarking analysts, and AI agents pulling daily job market signals.

<!-- skootle:review-cta -->
> Try it on a small dataset, then let us know what you think in a [review](https://apify.com/skootle/glassdoor-jobs-reviews/reviews).

---

### What does Glassdoor Jobs Scraper do?

This actor takes a **Glassdoor search URL** (the exact one you'd paste from your browser after running a search on glassdoor.com) and returns every job listing on that page as a clean, structured record. Each record contains:

- **Identity** — job ID, listing URL, job title, hiring company
- **Location** — city/state string, plus a derived `isRemote` boolean
- **Money** — raw salary text (`"$120K - $180K"`) *plus* numeric `salaryEstimateLowUsd` and `salaryEstimateHighUsd` fields. Per-hour salaries are automatically annualized at 2080 hours so you can sort across hourly and salaried roles in one column.
- **Recency** — both the relative posting age (`"2d"`, `"30+d"`) and an ISO 8601 `postedDate` plus integer `daysPosted`, so you can filter `daysPosted < 7` directly in SQL or pandas.
- **Classification** — typed enums for `employmentType` (`FULL_TIME` / `PART_TIME` / `CONTRACT` / `INTERNSHIP` / ...) and `experienceLevel` (`INTERN` / `ENTRY` / `MID` / `SENIOR` / `STAFF_PRINCIPAL` / `EXECUTIVE`) inferred from the title and salary text.
- **Employer signal** — `companyRating` (Glassdoor's 1.0-5.0 score) so you can filter for top-rated employers in one query.
- **Description** — the first few sentences of the listing as it appears in Glassdoor's preview.
- **Drop-into-LLM card** — a 300-500 character `agentMarkdown` field per record. Paste any row into Claude, ChatGPT, Slack, or your CRM and it renders as a clean summary with title, company, location, salary, rating, and link — no extra formatting needed.
- **Self-filter signal** — a `fieldCompletenessScore` (0-100) per record so you can drop rows that are too sparse for your downstream pipeline.

The actor does not require you to bring an API key. Paste a Glassdoor search URL, set `maxItems`, run.

### Why scrape Glassdoor?

Glassdoor's job inventory is the broadest single source of US job postings outside LinkedIn — millions of active listings across every industry, with the unique addition of employer-rated context (rating, review count, salary signal) that no plain job board carries. The listings themselves are public, but the data is locked inside JavaScript-rendered search results behind anti-bot defenses tuned to block naive scraping. **Plain HTTP doesn't work** — Glassdoor's bot detection blocks `curl` and basic headless Chrome. This actor handles that for you with a stealth-Chromium backbone running on a private Oracle Cloud egress, so you get the data without managing your own proxy infrastructure.

The dataset is valuable because it sits between three buyer workflows:

1. **Lead enrichment for cold outreach** — every company hiring an engineer in your metro is a warm sales target.
2. **Salary intelligence** — numeric `salaryEstimateLowUsd` / `salaryEstimateHighUsd` lets you benchmark roles in minutes.
3. **Hiring market timing** — `daysPosted` plus a daily watchlist run tells you which companies are scaling, freezing, or quietly hiring.

### Who needs this?

- **Technical recruiters** sourcing engineers, PMs, and designers in specific metros, who today open Glassdoor and copy-paste 30 listings into a spreadsheet by hand.
- **B2B sales reps and lead-gen agencies** building outreach lists for ATS vendors, payroll, dev tools, and recruiting SaaS — every company hiring an engineer is a warm prospect.
- **Salary benchmarking analysts** at HR consulting firms who need fresh numeric salary ranges for compensation surveys.
- **Competitive intelligence teams** monitoring which companies in their space are scaling teams, opening new offices, or pivoting to new tech stacks (revealed via job titles).
- **AI agents and LLM-powered workflows** that need a structured, schema-stable view of the job market — `agentMarkdown` plus a fixed schema means your LangChain / CrewAI / Claude-Code pipeline doesn't break when Glassdoor tweaks their HTML.
- **Solo founders and indie hackers** validating product ideas by counting how many companies post specific job titles week-over-week.

### How to use Glassdoor Jobs Scraper

1. Open [glassdoor.com](https://www.glassdoor.com) and run the search you want (keyword + location + filters).
2. Copy the URL from your browser's address bar. It looks like `https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm`.
3. Paste that URL into the `jobsSrpUrl` input on this actor.
4. Set `maxItems` (start with 10 for a trial; production runs commonly use 100-500).
5. Click **Start**. Each page returns ~30 listings. The actor stops when `maxItems` is reached, when `maxPages` is exhausted, or when a page returns zero new jobs.
6. Download the dataset as JSON, CSV, or XLSX, or pipe it directly into your destination via Apify's API, webhook, or one of the 100+ integrations (Slack, Make, Zapier, Google Sheets, Airtable, etc.).

### How much will scraping Glassdoor cost?

Pay-per-result tiered pricing. The `apify-actor-start` fee is $0.001 per run (a fraction of a cent — fires once whether you save 5 records or 5,000). The per-job-listing event price varies by your Apify plan:

| Apify plan | Per-job price | Cost per 1,000 jobs |
|---|---|---|
| FREE | $0.0003 | $0.30 |
| BRONZE | $0.0005 | $0.50 |
| SILVER | $0.0006 | $0.60 |
| GOLD | $0.0007 | $0.70 |
| PLATINUM | $0.0007 | $0.70 |
| DIAMOND | $0.0007 | $0.70 |

A typical daily watchlist run pulling 100 jobs costs $0.03–$0.07 in event fees plus a few cents of Apify platform usage (compute + bandwidth, billed by Apify directly). You only pay for records actually saved to the dataset — runs that return zero results cost only the $0.001 start fee.

Free-tier Apify users get $5 in monthly platform credit, which yields roughly **1,600+ free trial records** on this actor before any out-of-pocket spend.

### Is it legal to scrape Glassdoor?

This actor scrapes **only public-facing job listing pages** that Glassdoor serves to any visitor without login. It does not bypass authentication, does not access private review or salary endpoints, and does not interact with any rate-limited API. The actor honors a reasonable request cadence and is designed for personal lead-gen, market intelligence, and analytics workflows.

That said: **public data is not the same as "free to redistribute"**. Glassdoor's Terms of Service restrict commercial republication of their content. If you plan to package this data into a downstream product you sell, get an opinion from your own counsel — not from us. For internal recruiting, sales prospecting, salary benchmarking, and AI-agent automation, the pattern is common industry practice. For building a competing job board or selling Glassdoor's listings to third parties, it isn't.

### Examples

#### Software engineers in NYC

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm",
  "maxItems": 50,
  "maxPages": 2
}
````

Use case: a recruiter at a YC company tracking which NYC startups are hiring backend engineers this week.

#### Product managers in San Francisco

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/san-francisco-product-manager-jobs-SRCH_IL.0,13_IC1147401_KO14,29.htm",
  "maxItems": 100
}
```

Use case: a PM tools vendor (Productboard, Linear) building a weekly outreach list of companies that just opened a PM role.

#### Remote data scientist roles (US-wide)

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/united-states-remote-data-scientist-jobs-SRCH_IL.0,13_IN1_KO14,35.htm",
  "maxItems": 200
}
```

Use case: a data-tools company (dbt, Hex, Mode) sourcing leads for self-serve outreach.

#### Sales reps in Chicago

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/chicago-sales-representative-jobs-SRCH_IL.0,7_IC1128808_KO8,28.htm",
  "maxItems": 50
}
```

Use case: a CRM reseller building a list of Chicago-area companies expanding their sales teams.

#### Junior dev roles for early-career sourcers

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/united-states-junior-developer-jobs-SRCH_IL.0,13_IN1_KO14,30.htm",
  "maxItems": 100
}
```

Use case: a bootcamp's career services team aggregating entry-level openings for cohort placement.

#### Marketing managers across major metros

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/marketing-manager-jobs-SRCH_KO0,17.htm",
  "maxItems": 300,
  "maxPages": 10
}
```

Use case: a marketing agency benchmarking salary ranges and rating distributions across competitors.

### Input parameters

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `mode` | enum | no | `"jobs"` | Mode of operation. v0.1 supports `"jobs"` only. `"reviews"` and `"both"` are reserved for a future build. |
| `jobsSrpUrl` | string (URL) | yes for `mode=jobs` | — | A pre-resolved Glassdoor search URL. Run the search you want on glassdoor.com first, then paste the URL from your address bar. |
| `companyReviewsUrl` | string (URL) | no | null | Reserved for v0.2 reviews mode. |
| `maxItems` | integer | no | 10 | Cap on total records saved. Use 10-25 for trials; bump to 100-500 for production. |
| `maxPages` | integer | no | 1 | Pagination cap. Each page returns ~30 jobs. |

### Glassdoor output format

#### `job_listing` record

| Field | Type | Description |
|---|---|---|
| `recordType` | enum | Always `"job_listing"` for this record type. |
| `outputSchemaVersion` | string | ISO date of this schema version (`"2026-05-13"`). Bumps on any breaking change. |
| `recordId` | string | Stable across runs. Format: `gd-jl-<jobId>`. |
| `jobId` | string | Glassdoor's internal job ID. |
| `listingUrl` | string (URL) | Direct link to the job detail page. |
| `title` | string | Job title. |
| `company` | string | Hiring company name. |
| `location` | string | City, state, or country. |
| `isRemote` | boolean | Derived from the location string. |
| `postedRelative` | string | Relative age as shown on Glassdoor (`"2d"`, `"30+d"`). |
| `postedDate` | string (ISO 8601) | Computed `YYYY-MM-DD`. |
| `daysPosted` | integer | Days since posting. |
| `employmentType` | enum | `FULL_TIME` / `PART_TIME` / `CONTRACT` / `TEMPORARY` / `INTERNSHIP` / `UNKNOWN`. |
| `experienceLevel` | enum | `INTERN` / `ENTRY` / `MID` / `SENIOR` / `STAFF_PRINCIPAL` / `EXECUTIVE` / `UNKNOWN`. |
| `salaryEstimateText` | string | Raw salary text as Glassdoor displays it. |
| `salaryEstimateLowUsd` | number | Numeric low end. Per-hour values annualized at 2080 hours. |
| `salaryEstimateHighUsd` | number | Numeric high end. Same normalization. |
| `companyRating` | number | Glassdoor employer rating (1.0-5.0). |
| `description` | string | Snippet from the listing's description. |
| `agentMarkdown` | string | Drop-into-LLM ready summary card (~300-500 chars). |
| `fieldCompletenessScore` | integer | 0-100. Filter sparse rows. |
| `scrapedAt` | string (ISO 8601) | Timestamp the record was saved. |

#### Example output

```json
{
  "recordType": "job_listing",
  "outputSchemaVersion": "2026-05-13",
  "recordId": "gd-jl-1010130768473",
  "jobId": "1010130768473",
  "listingUrl": "https://www.glassdoor.com/job-listing/php-software-engineer-cybercoders-JV_KO0,21_KE22,33.htm?jl=1010130768473",
  "title": "PHP Software Engineer",
  "company": "CyberCoders",
  "location": "United States",
  "isRemote": false,
  "postedRelative": "2d",
  "postedDate": "2026-05-12",
  "daysPosted": 2,
  "employmentType": "UNKNOWN",
  "experienceLevel": "MID",
  "salaryEstimateText": "$100K - $120K (Employer provided)",
  "salaryEstimateLowUsd": 100000,
  "salaryEstimateHighUsd": 120000,
  "companyRating": 3.9,
  "description": "Bachelors degree in computer science or a related field, coding bootcamp, or equivalent practical experience...",
  "agentMarkdown": "**PHP Software Engineer** @ CyberCoders\n- 📍 United States\n- 💰 $100K - $120K (Employer provided)\n- 🏷 UNKNOWN · MID\n- 🕒 2d\n- ⭐ 3.9\n- 🔗 https://www.glassdoor.com/job-listing/...",
  "fieldCompletenessScore": 90,
  "scrapedAt": "2026-05-14T00:59:56.188Z"
}
```

### During the Actor run

The actor reads your input, validates the search URL, then walks pages serially (one fetch at a time) through a stealth-Chromium backbone. Each page takes ~20-30 seconds end-to-end including the bot-defense challenge resolution. A `AGENT_BRIEFING.md` digest is written to the run's key-value store at finish, summarizing record count, salary distribution, remote share, and the top 10 most-complete records — useful for daily Slack drops or LLM context windows.

If the actor returns zero records on a given page, pagination stops automatically — this prevents wasted runs on URLs that resolve to a redirect or filter-collapsed result.

### FAQ

#### How does Glassdoor Jobs Scraper work?

You provide a real Glassdoor search URL (one you'd paste from your own browser). The actor fetches each results page using a stealth-Chromium backbone designed to clear Glassdoor's anti-bot defenses, parses the ~30 job cards on each page using current selectors (not legacy ones that broke months ago), and saves a typed record per job. Repeat for as many pages as you configure.

#### Where do I get the Glassdoor search URL?

Open glassdoor.com, run the exact search you want (e.g., "software engineer in New York"), then copy the URL from your address bar after the page loads. The URL will contain codes like `SRCH_IL.0,8_IC1132348_KO9,26.htm` — those are Glassdoor's internal location and keyword IDs. The actor passes them through verbatim.

#### Can I monitor only new records since the last run?

Not yet in v0.1 — but the record IDs are idempotent (`gd-jl-<jobId>` is the same across runs), so you can dedupe downstream by storing seen IDs in a key-value store, database, or Apify's own dataset. A `watchlistMode` flag that auto-emits only new records since last run is planned for v0.2.

#### Can I integrate this with Make, Zapier, n8n, Slack, or my CRM?

Yes — Apify provides 100+ native integrations including Slack, Make, Zapier, n8n, Google Sheets, Airtable, Salesforce, HubSpot, Webflow, and a generic webhook output. You can also call the actor directly from any HTTP client using your Apify API token; the dataset is queryable as JSON, CSV, XLSX, or RSS.

#### Can I use this from Python or Node?

Yes — Apify ships an [Apify Python client](https://docs.apify.com/api/client/python) and [Apify JS client](https://docs.apify.com/api/client/js) for actor runs and dataset retrieval. Both are pip / npm installable and authenticate with the same API token you use elsewhere.

#### Why does this cost more than the free Glassdoor scrapers on the Store?

Free scrapers run on minimal infrastructure with no anti-bot defense and break monthly when Glassdoor tweaks their HTML or rate-limits their proxy pool. Their daily auto-test silently fails, their dataset goes empty, and your downstream pipeline starts returning zero rows without warning. The per-result cost on this actor ($0.0003–$0.0007) pays for an actively maintained stealth backbone, a versioned schema with bump-on-breaking-change policy, and a daily reliability test that catches breakage in 24h instead of weeks.

#### Will Glassdoor block me?

The actor uses a stealth-Chromium backbone on a low-traffic egress, so individual buyers don't carry their own IP reputation risk. Glassdoor's defenses target naive `curl` and obvious headless Chrome — this actor passes their commercial-grade fingerprint checks (verified on bot.sannysoft.com and browserscan.net at "Normal" / no detection). For very high-volume runs (10k+ jobs/day), throttle with smaller `maxItems` per run instead of one mega-run.

#### Why doesn't v0.1 include reviews or salaries?

Glassdoor's `/Reviews/` and `/Salaries/` paths sit behind a stricter Cloudflare layer than the `/Job/` path. The current cloak backbone clears the jobs path cleanly but doesn't yet auto-solve the interactive Cloudflare challenge on reviews. v0.2 will add reviews using a humanized cloak profile.

#### How fresh is the data?

Each run fetches live HTML from Glassdoor at run time — there is no caching layer between the source and your dataset. Jobs posted in the last hour appear with `daysPosted: 0`.

#### What is `agentMarkdown`?

It's a pre-formatted ~300-character markdown summary baked into every record. Drop any row into Claude, ChatGPT, Slack, a CRM note field, or an email draft and it renders as a clean card with title, company, location, salary, rating, and link — no string-templating on your end. It exists because AI agent buyers were the loudest "this is the best output schema we've seen" feedback on our other actors; we ship it on every skootle actor now.

#### Can I run this on a schedule?

Yes — Apify has native scheduling: pick a cron expression, set the input once, and Apify will run the actor automatically and pipe results into your destination via integrations or webhooks. Most buyers run this as a daily watchlist.

### Why choose Glassdoor Jobs Scraper

- **Numeric salary mirrors** — every salary field has both the raw text and a typed numeric (per-hour values annualized) so you can sort, filter, and average without writing parser code.
- **ISO 8601 everywhere** — `postedDate` and `scrapedAt` are real ISO timestamps. Sort by `daysPosted` directly in pandas, BigQuery, Postgres, or Airtable.
- **Typed enums for classification** — `employmentType` and `experienceLevel` are stable enum values, not raw source strings. Your downstream code doesn't have to handle 12 variants of "Senior" vs "Sr.".
- **Versioned schema** — `outputSchemaVersion: "2026-05-13"` literal on every record plus a bump-on-breaking-change policy. Your pipeline doesn't silently break when we ship improvements.
- **Idempotent record IDs** — `recordId` is stable across runs for the same job. Dedupe downstream without state.
- **Field completeness score** — `fieldCompletenessScore: 0-100` per record so you can filter sparse rows in one query.
- **AGENT\_BRIEFING.md per run** — run-level markdown digest written to the key-value store. Pipe it into Slack or feed it to an LLM context window for a daily summary.
- **Currently maintained selectors** — most free Glassdoor scrapers grep legacy DOM classes that broke months ago and now return zero parsed cards on real pages. This actor targets the current `JobCard_*` taxonomy and is verified against a fresh page on every release.

#### Your feedback

Hit a bug or want a feature? Open an issue on the [Issues tab](https://apify.com/skootle/glassdoor-jobs-reviews/issues/open) rather than the reviews page, and we'll fix it fast (typically within 48 hours).

### Other Skootle actors you might want to check

- 🏢 [Wellfound Jobs Scraper](https://apify.com/skootle/wellfound-jobs-scraper) — startup hiring inventory with company funding signals.
- 📋 [Greenhouse Jobs Scraper](https://apify.com/skootle/greenhouse-jobs-scraper) — every role on any company's Greenhouse board.
- 🌱 [Lever Jobs Scraper](https://apify.com/skootle/lever-jobs-scraper) — same but for Lever-hosted boards.
- 🇺🇸 [SAM.gov Federal Contracts](https://apify.com/skootle/sam-gov-federal-contracts) — federal contract opportunities with USAspending award history.
- 📰 [HackerNews Watchlist](https://apify.com/skootle/hackernews-watchlist) — daily HN signal filtered for your keywords.
- 🐙 [GitHub Trending Repos](https://apify.com/skootle/github-trending) — daily/weekly/monthly trending across languages.

### Support and contact

- 🐛 [Open an issue](https://apify.com/skootle/glassdoor-jobs-reviews/issues/open) for bugs or feature requests
- 📝 [Leave a review](https://apify.com/skootle/glassdoor-jobs-reviews/reviews) after a successful run
- 🌐 [skootle on Apify](https://apify.com/skootle) for the full actor catalog

# Actor input Schema

## `mode` (type: `string`):

What to scrape. v0.1 supports `jobs` only. `reviews` and `both` are reserved for a future build.

## `jobsSrpUrl` (type: `string`):

Pre-resolved Glassdoor SRP URL (one with `SRCH_IL.<x>,<y>_IC<locId>_KO<a>,<b>.htm` codes). Run the search you want on glassdoor.com first, then paste the URL from the address bar here.

## `companyReviewsUrl` (type: `string`):

Reviews mode is reserved for v0.2 — Glassdoor /Reviews/ paths currently fail a Cloudflare challenge. Leave blank for v0.1.

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

Cap on total records saved per run. Keep low (≤10) for trial runs; bump for production.

## `maxPages` (type: `integer`):

Pagination cap. Each page returns ~30 jobs.

## Actor input object example

```json
{
  "mode": "jobs",
  "jobsSrpUrl": "https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm",
  "maxItems": 10,
  "maxPages": 1
}
```

# 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 = {
    "jobsSrpUrl": "https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm"
};

// Run the Actor and wait for it to finish
const run = await client.actor("skootle/glassdoor-jobs-reviews").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 = { "jobsSrpUrl": "https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm" }

# Run the Actor and wait for it to finish
run = client.actor("skootle/glassdoor-jobs-reviews").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "jobsSrpUrl": "https://www.glassdoor.com/Job/new-york-software-engineer-jobs-SRCH_IL.0,8_IC1132348_KO9,26.htm"
}' |
apify call skootle/glassdoor-jobs-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=skootle/glassdoor-jobs-reviews",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Glassdoor Jobs Scraper",
        "description": "Scrape Glassdoor job listings with numeric salary range (USD), employer rating, ISO posted date, employment type, and experience level. Stable record IDs for daily watchlist dedupe. Drop-into-LLM summary card per record. Export, run via API, schedule, or integrate with other tools.",
        "version": "0.1",
        "x-build-id": "j8ZpEMXpnLbu92Iik"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/skootle~glassdoor-jobs-reviews/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-skootle-glassdoor-jobs-reviews",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/skootle~glassdoor-jobs-reviews/runs": {
            "post": {
                "operationId": "runs-sync-skootle-glassdoor-jobs-reviews",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/skootle~glassdoor-jobs-reviews/run-sync": {
            "post": {
                "operationId": "run-sync-skootle-glassdoor-jobs-reviews",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "jobs",
                            "reviews",
                            "both"
                        ],
                        "type": "string",
                        "description": "What to scrape. v0.1 supports `jobs` only. `reviews` and `both` are reserved for a future build.",
                        "default": "jobs"
                    },
                    "jobsSrpUrl": {
                        "title": "Glassdoor jobs search URL",
                        "type": "string",
                        "description": "Pre-resolved Glassdoor SRP URL (one with `SRCH_IL.<x>,<y>_IC<locId>_KO<a>,<b>.htm` codes). Run the search you want on glassdoor.com first, then paste the URL from the address bar here."
                    },
                    "companyReviewsUrl": {
                        "title": "Glassdoor reviews URL (v0.2 — not yet active)",
                        "type": "string",
                        "description": "Reviews mode is reserved for v0.2 — Glassdoor /Reviews/ paths currently fail a Cloudflare challenge. Leave blank for v0.1."
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Cap on total records saved per run. Keep low (≤10) for trial runs; bump for production.",
                        "default": 10
                    },
                    "maxPages": {
                        "title": "Max pages",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "Pagination cap. Each page returns ~30 jobs.",
                        "default": 1
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
