# Glassdoor Scraper — Glassdoor Jobs API with Salaries | $0.30/1k (`glasswing/glassdoor-jobs-scraper`) Actor

Scrape Glassdoor jobs by keyword, location or Glassdoor URL: title, company, Glassdoor rating, salary range (min, median, max), job type, remote flag, Easy Apply, skills, posting age and optional full description. No login, proxy included. Export CSV, JSON or Excel.

- **URL**: https://apify.com/glasswing/glassdoor-jobs-scraper.md
- **Developed by:** [Raffy](https://apify.com/glasswing) (community)
- **Categories:** Jobs, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 jobs

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

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

## What's an Apify Actor?

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

### What does Glassdoor Jobs Scraper do?

Get Glassdoor job listings as clean, analysis-ready rows: title, company, the company's **Glassdoor rating**, location, the **salary range** as numbers (`salaryMin`, `salaryMedian`, `salaryMax`), job type, remote or hybrid flag, Easy Apply, skills, how many days ago the job was posted, a description snippet and, if you want it, the **full job description**. It is built for recruiters, salary analysts, job boards and sales teams who need Glassdoor listings in bulk instead of one browser tab at a time.

Type a keyword and a location - or paste a Glassdoor search URL - and **scrape Glassdoor jobs** into JSON, CSV or Excel, or read them straight from the Apify API. It works as a practical **Glassdoor API alternative** for job search: Glassdoor's own partner API is not open to the public, and this Actor reads the same job-search data the Glassdoor website shows to every visitor. The default 20-job run finished in **about 15 seconds**.

It reads only job listings that Glassdoor shows publicly. It does **not** log in, does not touch company reviews, interviews, resumes or member profiles, and has no recruiter, email or phone-number columns. If an employer pasted an email address, phone number or a contact person's name into the posting text, it is replaced with `[email removed]`, `[phone removed]`, `[profile link removed]` or `[contact removed]` before the row is saved. That includes the contact person in the "Agency contact information" block of federal job postings.

### Use cases for this Glassdoor scraper

- **Compensation analyst tracking pay.** Glassdoor shows a pay range on most US listings. `salaryMin`, `salaryMedian` and `salaryMax` come as numbers with `salaryPeriod` and `salaryCurrency`, and `salaryIsEstimate` separates the employer's own range from Glassdoor's estimate. 19 of the 20 jobs in the default run had one.
- **Recruiting or staffing agency building a client pipeline.** Pull every new nurse, warehouse or software opening in a city each morning with `datePosted: "1"` and reach the hiring company first. `companyRating` tells you how the employer is seen by its own staff.
- **Sales team finding companies that are hiring.** A company posting ten data roles is buying a data stack. Group the rows by `company` and `skills` and push the accounts into your CRM as hiring-intent signals.
- **Job board or aggregator seeding listings.** Title, company, logo, location, salary, job type and a link to the Glassdoor listing, with the full description on request.
- **Labour-market research.** Compare remote versus on-site volume, pay bands or skill demand by city, state or country with `workplaceType`, `location`, `skills` and the salary columns.
- **AI agents and RAG pipelines.** Every row is self-describing, inputs are plain strings, and the Actor can be called with no input at all.

### What data you get from every Glassdoor job

One row per job listing. Every column below exists in the dataset schema; the **Overview** table view shows `title`, `company`, `location`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `companyRating`, `postedDaysAgo`, `easyApply`, `url`, `status` and `error`.

**Row status and provenance**

| Field | Type | Description |
|---|---|---|
| `url` | string | Glassdoor job listing page (`https://www.glassdoor.com/job-listing/...htm?jl=...`). For `not_found` and `error` rows, the Glassdoor request that failed; its `f_kw` (keyword) and `f_loc` (location) parameters name the search. |
| `status` | string | `ok`, `not_found` or `error` (see the table below). |
| `error` | string | Reason when `status` is not `ok`. Absent on `ok` rows. |
| `scrapedAt` | string | ISO 8601 time of extraction. |
| `searchKeyword` | string | Keyword of the search that found the job. |
| `searchLocation` | string | Location you typed for that search. |
| `searchUrl` | string | The Glassdoor URL from your input that found the job, when you gave one. |

**Job**

| Field | Type | Description |
|---|---|---|
| `jobId` | string | Glassdoor's job listing id (the `jl` in job URLs). Use it to deduplicate across runs. |
| `title` | string | Job title as published. |
| `occupation` | string | Glassdoor's normalised occupation for the title, e.g. `data analyst`. |
| `jobTypes` | array | `full-time`, `part-time`, `contract`, `temporary`, `internship`, `permanent`, ... when Glassdoor tags them. |
| `remote` | boolean | True when the job is marked remote. |
| `workplaceType` | string | `remote` or `hybrid`, when Glassdoor says so. |
| `easyApply` | boolean | The job has Glassdoor's Easy Apply button. |
| `sponsored` | boolean | The listing is a sponsored (paid) placement. |
| `postedDaysAgo` | integer | Days since the job was posted on Glassdoor. |
| `skills` | array | Skills Glassdoor extracted from the posting, e.g. `SQL`, `Spark`, `Communication skills`. |
| `tags` | array | Other attributes: benefits, seniority, education, shifts, e.g. `401(k)`, `Senior level`, `Bachelor's degree`. |

**Company**

| Field | Type | Description |
|---|---|---|
| `company` | string | Hiring company name. |
| `companyId` | integer | Glassdoor employer id. |
| `companyRating` | number | The company's overall Glassdoor rating, 1 to 5. Absent when the company has no reviews. |
| `companyLogo` | string | Company logo image URL. |

**Location**

| Field | Type | Description |
|---|---|---|
| `location` | string | Location as Glassdoor shows it: `Buffalo, NY`, `London, England`, a state, or `Remote`. |
| `locationId` | integer | Glassdoor location id. |
| `locationType` | string | `city`, `state`, `country` or `metro`. |

**Pay**

| Field | Type | Description |
|---|---|---|
| `salaryMin` | number | Low end of the pay range (Glassdoor's 10th percentile). |
| `salaryMedian` | number | Middle of the range. |
| `salaryMax` | number | High end of the range (90th percentile). |
| `salaryPeriod` | string | `hour`, `day`, `week`, `month` or `year`. |
| `salaryCurrency` | string | ISO 4217 currency code, e.g. `USD`, `GBP`. |
| `salaryIsEstimate` | boolean | `false` when the employer published the pay, `true` when it is Glassdoor's estimate. |

**Posting text**

| Field | Type | Description |
|---|---|---|
| `snippet` | string | The description preview Glassdoor shows in search results. On every `ok` row. |
| `description` | string | The full description as plain text with line breaks, contact details removed. Only with **Include full description** on. |
| `descriptionHtml` | string | The full description as HTML, contact details removed. Only with **Include description HTML** on as well. |
| `descriptionError` | string | Why the full description is missing, when you asked for it and it could not be fetched. |

A field is simply omitted when Glassdoor does not publish it. In the default run all 20 jobs had a title, company, location, posting age, skills and snippet; 19 had a salary range, 15 a company rating and 16 a job type.

#### Result status (tri-state output)

| `status` | Meaning | Billed? |
|---|---|---|
| `ok` | The job was found and extracted. | Yes |
| `not_found` | Glassdoor answered, but the search has no matches, or the location you typed is not on Glassdoor. | No |
| `error` | Glassdoor could not be read after retries (network error, block, or a change on Glassdoor's side), or an input entry was not a Glassdoor search URL. `error` says why. | No |

### How to scrape Glassdoor jobs with this Actor

1. Open the Actor in Apify Console and click **Try for free**.
2. Type one or more **Keywords** (one search per line) and a **Location** (`Chicago, IL`, `Texas`, `London`, `United Kingdom`, `Remote`). Or paste Glassdoor search URLs from your browser into **Glassdoor search URLs** - they keep their own keyword, location and filters.
3. Optionally set **Date posted**, **Job type**, **Remote jobs only**, **Easy Apply only**, **Minimum company rating** and **Radius**.
4. Turn on **Include full description** if you need the complete posting text (billed as a separate event, only for jobs whose description was fetched).
5. Set **Maximum jobs** (start with the default 20 to see the output) and click **Start**.
6. Open the **Output** tab or **Export** the dataset as JSON, CSV, Excel, XML or HTML.

To automate it, use the **API** tab (Node.js, Python, curl examples) or add a **Schedule**.

### Input

Every field is optional - the prefilled values already produce a complete run. See the **Input** tab for the full schema.

| Field | Type | Default | When to change it |
|---|---|---|---|
| `keywords` | array of strings | `["software engineer"]` | The job titles or skills you want, one search per line, e.g. `registered nurse`, `forklift driver`. |
| `location` | string | empty (all locations) | City, state or country as you would type it on Glassdoor (`Chicago, IL`, `Texas`, `London`, `Berlin`, `United Kingdom`, `Remote`). The best match from Glassdoor's location list is used. |
| `radius` | integer | Glassdoor's default | Miles around a city: 0, 5, 10, 15, 25, 50 or 100. |
| `datePosted` | string | `any` | `1`, `3`, `7`, `14` or `30` days. Use `1` on a daily schedule so you only pay for fresh postings. |
| `jobType` | string | `any` | `fulltime`, `parttime`, `contract`, `internship` or `temporary`. |
| `remoteOnly` | boolean | `false` | Only remote jobs. |
| `easyApplyOnly` | boolean | `false` | Only jobs with Easy Apply. |
| `minRating` | string | `any` | `1` to `4`: only companies with at least that Glassdoor rating. |
| `maxItems` | integer | `20` | Your main spending cap: the Actor never saves more jobs than this, with or without descriptions. With several keywords or URLs it is split evenly between them. |
| `includeDescription` | boolean | `false` | Turn on for the full `description` of every job, billed as the `job-details` event only for jobs whose description was actually fetched. The run first opens one browser session, then adds one request per job. Measured on the platform in 18 description runs (2026-10-16): the session was ready 6 to 50 seconds after the run started in 16 of them (median about 20 seconds) and after 76 seconds once, when the first IP address was refused. In 1 run all four attempts were refused after about 90 seconds; its jobs were saved with the snippet and `descriptionError`. |
| `includeDescriptionHtml` | boolean | `false` | With full descriptions on, also save `descriptionHtml`. |
| `startUrls` | array of strings | one example search URL | Glassdoor job search URLs, e.g. `https://www.glassdoor.com/Job/chicago-il-us-registered-nurse-jobs-SRCH_IL.0,13_IC1128808_KO14,30.htm`, also from glassdoor.co.uk, .ca and the other Glassdoor sites. The URL's own filters (`fromAge`, `jobType`, `minRating`, `applicationType`, `remoteWorkType`, `radius`) are kept; a `sortBy` in the URL is ignored (see Limitations). When you type your own keywords, the built-in example URL is skipped. |

There is no proxy field: the Actor always uses an Apify residential proxy, which Glassdoor requires. It is included in the price.

Example input (exactly the prefilled default):

```json
{
    "keywords": ["software engineer"],
    "maxItems": 20,
    "startUrls": ["https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"]
}
```

A daily feed of fresh, well-rated nursing jobs in Chicago with full descriptions:

```json
{
    "keywords": ["registered nurse", "nurse practitioner"],
    "location": "Chicago, IL",
    "datePosted": "1",
    "minRating": "4",
    "includeDescription": true,
    "maxItems": 300,
    "startUrls": []
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. A real row from the default run (2026-10-16; `tags` shortened here), followed by what a search without matches returns:

```json
[
    {
        "url": "https://www.glassdoor.com/job-listing/associate-business-analyst-client-macquarie-group-JV_IC1132348_KO0,33_KE34,49.htm?jl=1010156795869",
        "status": "ok",
        "scrapedAt": "2026-10-16T15:46:05.328Z",
        "jobId": "1010156795869",
        "title": "Associate Business Analyst, Client",
        "company": "Macquarie Group Limited",
        "companyId": 12088,
        "companyRating": 3.6,
        "companyLogo": "https://media.glassdoor.com/sql/12088/macquarie-group-squareLogo-1684797770187.png",
        "location": "New York, NY",
        "locationId": 1132348,
        "locationType": "city",
        "salaryMin": 145000,
        "salaryMedian": 155000,
        "salaryMax": 165000,
        "salaryCurrency": "USD",
        "salaryPeriod": "year",
        "salaryIsEstimate": false,
        "postedDaysAgo": 134,
        "easyApply": false,
        "sponsored": true,
        "jobTypes": ["full-time"],
        "remote": false,
        "occupation": "business analyst",
        "skills": ["Jira", "Kanban", "Analysis skills", "Requirements analysis", "Risk management", "Requirements management", "Communication skills"],
        "tags": ["Paid parental leave", "Requirements design", "Health savings account", "Disability insurance", "Mid-level", "Dependent care reimbursement", "Health insurance"],
        "snippet": "Macquarie Asset Management’s Digital Solutions team sits at the core of our digitalization strategy, enabling scalability, driving operational efficiency,…",
        "searchKeyword": "data analyst",
        "searchUrl": "https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"
    },
    {
        "url": "https://www.glassdoor.com/job-search-next/bff/jobSearchResultsQuery?f_kind=search&f_kw=zzqxqvbnonexistentjobxyz&f_loc=Seattle%2C+WA&f_lid=1150505&f_lt=CITY&f_max=5&f_i=0&f_p=1&f_n=0",
        "status": "not_found",
        "error": "No results for this page",
        "scrapedAt": "2026-10-16T15:40:39.875Z"
    }
]
```

With **Include full description** on, each row also carries `description` (plain text) and, with **Include description HTML**, `descriptionHtml`.

### How much does it cost to scrape Glassdoor?

This Actor uses **pay-per-event** pricing. The residential proxy and the platform compute are included:

| Event | Price | Charged when |
|---|---|---|
| Actor start | $0.005 per run | Once when the run starts. The platform charges one event per GB of memory and the Actor runs on 1 GB, so this is one event. |
| Job | $0.0003 per job ($0.30 per 1,000) | One job from the search results with `status: ok` was saved to the dataset. |
| Full job description | $0.001 per job ($1 per 1,000) | On top of the job, only with **Include full description** on and only when that job's full description was actually fetched and saved. A job that carries `descriptionError` instead is not charged this event. |

What typical runs cost:

| Run | Jobs | Descriptions | Price |
|---|---|---|---|
| Default run | 20 | off | $0.011 ($0.005 + 20 x $0.0003) |
| Daily feed | 100 | off | $0.035 |
| Daily feed with descriptions | 100 | 100 | $0.135 ($0.005 + 100 x $0.0003 + 100 x $0.001) |
| Market scan | 1,000 | off | $0.305 |
| Market scan with descriptions | 1,000 | 1,000 | $1.305 |

You are never charged for a row with `status` `not_found` or `error`. A job found by two of your searches is saved once. The free Apify plan's $5 of monthly credit covers about 16,000 jobs without descriptions, or about 3,800 with them. Small description runs are fine: 5 jobs with full descriptions cost $0.0115.

You can cap spending per run with **Maximum jobs** and with the run's **Max total charge** option; the Actor stops gracefully when either limit is reached and keeps everything it has already saved.

### How it compares

This Actor reads the JSON that Glassdoor's own job-search page loads, 100 jobs per request, so a 1,000-job run takes well under a minute and needs no browser. Only full descriptions need one browser visit at the start of the run (see **Input** for measured times), after which they are read the same fast way. You get flat, typed columns (numbers for pay, booleans for remote and Easy Apply), skills on every row, and a tri-state status you can trust inside an automated pipeline.

It is not for you if you need company reviews, interview reports, salaries pages or anything inside a Glassdoor account; employer contact names, emails or phone numbers (this Actor removes them on purpose); or a vendor-backed feed with a stability guarantee.

### Integrations, exports and API access

Results export to **CSV, JSON, Excel**, XML and HTML from the **Output** tab or the dataset API. From there, Apify integrations and webhooks push the same rows into **Google Sheets, Airtable or a CRM**, plus Slack, Amazon S3 or your own endpoint - directly, or through Zapier, Make and n8n. Add a **Schedule** with `datePosted: "1"` and today's new postings land in your sheet every morning.

The Actor can also be called from the **Apify API** (Node.js, Python and curl snippets are on the **API** tab), from the **Apify MCP server**, or by any AI agent that can call a tool: the inputs are plain strings and numbers, and every row carries `status` and `error`, so an agent can tell an empty search apart from a failure without parsing prose.

### Tips

- Keep `maxItems` small while testing, then raise it.
- Put several keywords in one run instead of many single-keyword runs; you pay the start fee once. `maxItems` is split evenly across them.
- To cover a large market, split it into narrower searches (per city, per keyword, per job type) rather than one very deep search.
- Use `jobId` to deduplicate rows across scheduled runs.
- Leave **Include full description** off when the snippet, skills and tags are enough: the run is faster and each job costs $0.0003 instead of $0.0013.
- For the newest jobs, use **Date posted** (`datePosted: "1"` on a daily schedule) and sort by `postedDaysAgo` yourself.
- With full descriptions, batch your searches into one run instead of many small runs: the browser session is opened once per run.

### Limitations

- **Undocumented data source.** The Actor reads the JSON behind Glassdoor's public job search. Glassdoor can change it at any time; when that happens rows come back as `error` (never silently wrong data) and the Actor is updated. Report it in the **Issues** tab.
- **No date sort.** Glassdoor's search does not return jobs in date order (it mixes in sponsored placements, and even its own "most recent" order is not by posting date), so this Actor does not offer a date sort it cannot keep. Use **Date posted** to get only fresh jobs; every row has `postedDaysAgo`.
- **Depth per search.** One search is read for at most 30 pages of 100 jobs, and Glassdoor itself usually stops earlier. Split large markets into narrower searches.
- **Full descriptions** depend on a short browser session that Glassdoor's security check accepts; the Actor tries up to four fresh IP addresses. In about one run out of ten none is accepted: the jobs are then still saved with the snippet and `descriptionError`, and charged only as jobs ($0.0003), not as full descriptions. Very long runs (over about 30 minutes) can lose the session part-way.
- **Salary and rating are optional.** Some listings carry no pay range, or only Glassdoor's estimate (`salaryIsEstimate: true`); companies without reviews have no rating.
- **Location matching.** A typed location uses Glassdoor's best match; for an exact place, paste a Glassdoor search URL instead.
- **No login and no personal data.** Company reviews, interview reports, member profiles and recruiter contact details are out of scope by design.
- Results reflect what Glassdoor published at the time of the run.

### FAQ

**Does this Actor need a Glassdoor account, an API key or my own proxy?** No. You only need an Apify account. There is no login step, and the residential proxy is set up and paid for by the Actor.

**Does it get the full job description?** Yes, when you turn on **Include full description**. Every row always has the `snippet` Glassdoor shows in search results.

**Does it work outside the United States?** Yes. Type a location such as `London`, `Toronto`, `Berlin` or `United Kingdom`, or paste a search URL from glassdoor.co.uk, glassdoor.ca or another Glassdoor site. Pay comes in the local currency.

**How do I get more results?** Raise `maxItems` first. For very large markets, split the search into several narrower ones (per city, per keyword, per job type) and run them together.

**Does it scrape Glassdoor reviews or salaries pages?** No. This Actor is for job listings only; the salary range shown on each job is included.

**What happens if Glassdoor changes something?** Rows come back with `status: error` and a reason instead of silently wrong data, so your pipeline can alert on it. You are not billed for `error` rows. Report it in the **Issues** tab with the run ID.

**Is it legal to scrape Glassdoor?** Scraping publicly available data is generally legal, but you are responsible for how you use the output. Read the legal notice below and Glassdoor's terms of service, and do not collect personal data without a legitimate reason.

**Can I sort by date?** No: Glassdoor's search does not return jobs in date order, so the Actor does not pretend to. Use **Date posted** (1, 3, 7, 14 or 30 days) and the `postedDaysAgo` column.

**Why did I get fewer rows than `maxItems`?** The search had fewer matches, or the run hit your **Max total charge** limit. Check the run log for "Stopping gracefully".

**Can I use this Actor from an AI agent or MCP client?** Yes. It runs with no input at all, every row is self-describing (`status` plus `error`), inputs are plain strings, and results can be fetched via the dataset API or the Apify MCP server.

### Related Actors

- [LinkedIn Jobs Scraper](https://apify.com/glasswing/linkedin-jobs-scraper) - use it for the same searches on LinkedIn, with seniority and applicant counts.
- [ATS Jobs Scraper](https://apify.com/glasswing/ats-jobs-scraper) - use it to read every opening straight from a company's own applicant-tracking system.
- [Dice Jobs Scraper](https://apify.com/glasswing/dice-jobs-scraper) - use it for US tech roles with skills and a visa-sponsorship flag.
- [Remote Jobs Scraper](https://apify.com/glasswing/remote-jobs-scraper) - use it for remote roles from remote-only job boards, merged and deduplicated.
- [Seek Jobs Scraper](https://apify.com/glasswing/seek-jobs-scraper) - use it for Australia and New Zealand, where Seek is the leading board.
- [JobStreet Scraper](https://apify.com/glasswing/jobstreet-scraper) - use it for Southeast Asia (Malaysia, Singapore, Philippines, Indonesia).
- [Indeed Scraper](https://apify.com/glasswing/indeed-jobs-scraper) - use it for Indeed job postings in 22 countries with parsed salary ranges and full descriptions.
- [Google Jobs Scraper](https://apify.com/glasswing/google-jobs-scraper) - use it to collect job postings that Google aggregates from many job boards in one search.

### Legal and data-protection notice

This Actor extracts only job listings that Glassdoor publishes publicly; it does not extract private user data such as reviewer or recruiter names, email addresses, phone numbers, gender or precise location of individuals (contact details found in free-text job descriptions are removed before the row is saved), and it does not log in or work around access controls. However, your results could still contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with Glassdoor's terms of service and applicable law when using the extracted data.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Glassdoor, Inc. or its owners. All trademarks belong to their respective owners.

# Changelog

This Actor's version history is a separate document: https://apify.com/glasswing/glassdoor-jobs-scraper/changelog.md

# Actor input Schema

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

Job titles or skills to search, one per line, as you would type them into Glassdoor's job search (for example `registered nurse`, `python developer`). Each line is one search. The built-in `software engineer` example is skipped when you paste your own search URLs.

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

City, state or country, as you would type it into Glassdoor's location box (for example `Chicago, IL`, `Texas`, `London`, `United Kingdom`, `Remote`). The best match from Glassdoor's own location list is used. Leave empty to search all locations.

## `radius` (type: `integer`):

Distance around a city location, in miles (Glassdoor offers 0, 5, 10, 15, 25, 50 and 100). Leave empty for Glassdoor's default.

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

Only jobs posted on Glassdoor within this many days.

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

Only jobs Glassdoor lists with this job type.

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

Only jobs Glassdoor marks as remote.

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

Only jobs with Glassdoor's Easy Apply button.

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

Only jobs at companies with at least this Glassdoor rating.

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

Stop after this many jobs in total; the Actor never saves more. With several keywords or URLs it is split evenly between them. Each job saved with status `ok` is one billable result.

## `includeDescription` (type: `boolean`):

Also fetch each job's full description (`description`, plain text), billed as a separate `job-details` event only for jobs whose description was actually fetched. The run opens one browser session first (see the README for measured times), then adds one request per job. Without it every job still has a short `snippet`.

## `includeDescriptionHtml` (type: `boolean`):

With full descriptions on: also save the description as HTML (`descriptionHtml`).

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

Glassdoor job search URLs, for example `https://www.glassdoor.com/Job/chicago-il-us-registered-nurse-jobs-SRCH_IL.0,13_IC1128808_KO14,30.htm`. Each URL keeps its own keyword, location and filters (`fromAge`, `jobType`, `minRating`, `applicationType`, `remoteWorkType`, `radius`). Clear the example if you only want your keywords.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "datePosted": "any",
  "jobType": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "minRating": "any",
  "maxItems": 20,
  "includeDescription": false,
  "includeDescriptionHtml": false,
  "startUrls": [
    "https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"
  ]
}
```

# 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"
    ],
    "maxItems": 20,
    "startUrls": [
        "https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("glasswing/glassdoor-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["software engineer"],
    "maxItems": 20,
    "startUrls": ["https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"],
}

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

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "software engineer"
  ],
  "maxItems": 20,
  "startUrls": [
    "https://www.glassdoor.com/Job/new-york-ny-us-data-analyst-jobs-SRCH_IL.0,14_IC1132348_KO15,27.htm"
  ]
}' |
apify call glasswing/glassdoor-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/g91iphQEQG9CvbwFR/builds/QSozNuYbZHuJ2OU9f/openapi.json
