# Glassdoor Jobs Scraper | Global Job Listings (`datascraperes/glassdoor-jobs-scraper`) Actor

Scrape public Glassdoor job listings worldwide with keyword, country, location, date, job type, remote, and Easy Apply filters. Get structured job data with descriptions, salaries, and direct application links for $1 per 1,000 unique offers.

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

## Pricing

$1.00 / 1,000 glassdoor offer returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Collect public Glassdoor job listings by keyword and country, with optional location, date, job-type, remote, and Glassdoor application filters. Each unique offer is returned as a structured Dataset item with available descriptions, compensation, employer details, and application URLs.

### What this Actor does

- Searches one Glassdoor country site per run with up to 50 keyword phrases.
- Applies optional location, publication-age, job-type, remote-only, and Glassdoor application filters.
- Returns up to 1,000 unique jobs per keyword and up to 50,000 items per run.
- Formats job descriptions as Markdown, HTML, or plain text.
- Optionally extracts public email addresses visible in job descriptions.
- Deduplicates offers across keywords while preserving the search phrase associated with each delivered item.
- Stores run-level counts, limits, failures, and billing reconciliation in the `SUMMARY` record.

### Use cases

- Source public vacancies for recruitment research.
- Compare hiring demand across keywords, locations, and countries.
- Monitor remote, contract, internship, and part-time opportunities.
- Analyze compensation and employer information when published.
- Build job-search alerts with Apify Tasks and Schedules.
- Export listings into spreadsheets, databases, CRMs, or internal dashboards.

### How to use

1. Open the Actor's **Input** tab.
2. Add one or more phrases under **Search keywords**.
3. Select a supported country and, optionally, enter a location.
4. Adjust the result limits and filters.
5. Click **Start**.
6. Open **Dataset** to inspect or export the job listings.

The Actor searches a single country site per run. Create separate runs when you need several countries.

### Input

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `keywords` | `string[]` | Yes | — | One to 50 job-search phrases. Blank and duplicate phrases are removed. |
| `country` | string | Yes | `"usa"` | Glassdoor country site, such as `usa`, `uk`, `canada`, `australia`, `germany`, `france`, `india`, `brazil`, `mexico`, or `spain`. |
| `location` | string or `null` | No | `null` | City, region, postal code, or another location understood by Glassdoor. |
| `maxItemsPerQuery` | integer | No | `25` | Maximum unique jobs per keyword, from 1 to 1,000. |
| `maxTotalItems` | integer | No | `5000` | Global Dataset limit across all keywords, from 1 to 50,000. |
| `offset` | integer | No | `0` | Results to skip per keyword, from 0 to 900. Offset plus `maxItemsPerQuery` cannot exceed 1,000. |
| `datePostedHours` | integer | No | `0` | Only jobs published within this many hours, from 0 to 720. Use `0` for any age. |
| `jobType` | string | No | `"any"` | `any`, `fullTime`, `partTime`, `contract`, or `internship`. |
| `remoteOnly` | boolean | No | `false` | Keep only listings identified as remote. |
| `easyApplyOnly` | boolean | No | `false` | Keep only jobs marked for Glassdoor application. |
| `descriptionFormat` | string | No | `"markdown"` | Return descriptions as `markdown`, `html`, or `plain`. |
| `includeEmails` | boolean | No | `false` | Extract public email addresses found in descriptions. |

This is the exact input used for the complete output example:

```json
{
  "keywords": [
    "software engineer"
  ],
  "country": "usa",
  "maxItemsPerQuery": 25,
  "maxTotalItems": 5000,
  "offset": 0,
  "datePostedHours": 0,
  "jobType": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "descriptionFormat": "markdown",
  "includeEmails": false,
  "location": null
}
```

### Output

The default Dataset contains one item per unique delivered job. Every successful item includes the search context, job identity, available employer and compensation data, the requested description format, and a retrieval timestamp.

| Field | Description |
| --- | --- |
| `success`, `status`, `source` | Result state and source identifier. |
| `searchKeyword`, `searchCountry`, `searchLocation` | Search context that produced the item. |
| `jobId`, `jobUrl`, `directJobUrl` | Job identity, Glassdoor listing URL, and direct application URL when available. |
| `title`, `companyName` | Public job title and employer name. |
| `companyUrl`, `companyDirectUrl` | Glassdoor company page and public company website when available. |
| `location`, `locationDisplay`, `isRemote` | Structured location, displayed location, and remote flag. |
| `jobTypes`, `postedDate` | Published job types and posting date when available. |
| `description`, `emails` | Job description in the selected format and optional public emails. |
| `compensation` | Published salary or compensation structure when available. |
| `companyIndustry`, `companyAddresses`, `companyEmployees`, `companyRevenue` | Available employer metadata. |
| `companyDescription`, `companyLogoUrl` | Available employer description and logo. |
| `scrapedAt` | Timestamp recorded when the item was collected. |

This is the complete Dataset item from a real successful run:

```json
{
  "success": true,
  "status": "success",
  "source": "glassdoor",
  "searchKeyword": "software engineer",
  "searchCountry": "United States",
  "searchLocation": null,
  "jobId": "gd-1010228441927",
  "jobUrl": "https://www.glassdoor.com/job-listing/j?jl=1010228441927",
  "directJobUrl": "https://www.glassdoor.com/partner/jobListing.htm?pos=101&ao=1110586&s=58&guid=000001a01e0ada47bcf07db6edeced4c&src=GD_JOB_AD&t=SR&vt=w&ea=1&cs=1_4186dde3&cb=1787210423383&jobListingId=1010228441927&cpc=217C45A42544DB93&jrtk=5-yul1-0-1k0f0lmjd2i39000-e61711bb6c9422ba---6NYlbfkN0AnsQJeHIrpK5UttAm4hLPttg48d_4BIU32tHFexz928XrxjBFz_olV1s-HBysSmSBjtMbazcrEYm2Aa3yWnRwxoy8teah3Hyq-xORr0FTtYJGRODqCehfRkR7imteXdqpPU3J_mUSbVO3e5M0YnB8h0wvh2JfmbD4Dv6-Kw4M4bpIFELbmCdKgCcg-BGixz1u8WmB6UJTh5fqimGdvLNiAUIBHqo2lqTDLbsKgLTrxSAszN7CDACKDaota__z4uCZgm9Y9Amt4jszzp0aKll3BDPwq8HwXA-I6ZFUBDIyPncPBtltMvwS1iVE231T7ijd8_5sVE45PehkAKP3DkTqiUNV_BK7OqVwwE8c2iZJcxY2oIPQ4yB3Ry6US80Yfwt7IS7mSr7Z3a9Zgisr44W3lKD4Ar1oVLztfxvZUS7GFrKPw2Vx1Q9R-b28idvx_KTRv-GfhI0NN6B2jPqRM6KRLh2JJW_3I9iZcx1zVGvUCgv-7JvHFNGQVI_-l-tnV1_hPQ_Dsy1ftsOEtQZKfoKL_ZcRF0bDTP6BYy6gESyStqrXVYkOToWMAYlNWIugMmtWx4R01d9bJIdMoaHXXSup5HD4JJb2FBJGgEJRZSmXKvidU3zqbytjjwYgUn4dNTEfPRZunfU6Lb7LOBc0aENrN3stpZbnNXK-4oX1vfhjLsBPdwGMTOkeaoz85hg17Dnj6ebfcPMjGC32QHIO1y9mwPKXiW85tq3jEFWFA4Hd6H9G6ZIcTFIHu7QN1Rc5nbLNYlfAgdFTSqOGloQD8rPxsKuKjEv2neNGhkMyTswbDOwPhtGpNYHgveftsbcQ7gSzHzionA1kc4XPcT8xw--F0vvh_PSEPVT8%3D",
  "title": "Automation Engineer - Beckhoff TwinCAT - USA",
  "companyName": "ekvip automation GmbH",
  "companyUrl": "https://www.glassdoor.com/Overview/W-EI_IE5913365.htm",
  "companyDirectUrl": null,
  "location": {
    "country": null,
    "city": "North Kingstown",
    "state": "RI"
  },
  "locationDisplay": "North Kingstown, RI",
  "isRemote": false,
  "jobTypes": [],
  "postedDate": "2026-08-13",
  "description": "ekvip automation GmbH is a software company specializing in mechanical and industrial engineering, headquartered in Leipzig with subsidiaries in the U.S. and Sarajevo. We develop TwinCAT 3 frameworks (including our open-source framework cinnamon), C# applications for the machine and line level, as well as services related to commissioning. Our guiding principle is simple: we shape automation.\n\nAre you looking for more than just a “job” and prefer to break new ground rather than follow well-trodden paths? We are looking for someone whose heart beats not only for automation technology, but also for adventure and challenges.\n\n**Your Tasks**\n\n* You will not only develop software for plant control and put it into operation but also help us build up the PLC programming business in the USA from scratch\n* You are responsible for designing and developing reusable framework libraries for use across diverse customer projects\n* You will work on improving and maintaining our existing frameworks to ensure stability, performance, and scalability\n* This also includes documenting architectural decisions and defining development standards for effective use of the framework\n* You will improve code quality and maintainability by applying modern software engineering principles and tools\n* Optimize workflows and evolve best practices in framework development\n* You will keep yourself informed about new trends and technologies in the fields of automation and software engineering\n* You will mentor and support less experienced team members, fostering a culture of collaboration and continuous learning\n* In the future, you will have the opportunity to build and lead your own development team\n\n**Your Profile**\n\n* Successfully completed studies in Electrical Engineering, Automation Engineering, Mechanical Engineering, Mechatronics, Computer Science, or a comparable technical field\n* At least 5 years of hands-on experience in PLC programming for special-purpose machines\n* Strong knowledge of IEC 61131-3 (Structured Text/SFC) with TwinCAT 3 and/or CODESYS 3\n* Experience in developing reusable libraries using TwinCAT 3 or CODESYS 3\n* Familiarity with library documentation, ideally using reStructuredText\n* Basic understanding of object-oriented programming (e.g., Java, Kotlin, C#)\n* Solid grasp of software architecture principles and modern software development techniques\n* Experience with NC applications and drive commissioning (e.g., Bosch Rexroth, Beckhoff)\n* In-depth knowledge of VisiWin 7 and/or Beckhoff HMI\n* Robot programming experience (e.g., KUKA, ABB, Stäubli) is a plus\n* willingness to travel extensively within the United States\n\n**Why you should start with us:**\n\n* Lots of freedom, responsibility, and the chance to build something from the ground up\n* Exciting projects that help you grow professionally and personally\n* Paid Time Off (PTO)\n* Paid Holidays & Sick Time\n* 401K Retirement Plan with Company Match\n* Health, Dental & Vision Insurance with Premium Paid by Company\n\nWork Location: In person",
  "emails": null,
  "compensation": {
    "interval": "yearly",
    "min_amount": 84391,
    "max_amount": 127383,
    "currency": "USD"
  },
  "companyIndustry": null,
  "companyAddresses": null,
  "companyEmployees": null,
  "companyRevenue": null,
  "companyDescription": null,
  "companyLogoUrl": "https://media.glassdoor.com/sql/5913365/ekvip-automation-squarelogo-1646993728233.png",
  "scrapedAt": "2026-08-20T07:20:35.107255Z"
}
```

Run-level information is stored separately in the default Key-Value Store under `SUMMARY`, including query counts, failures, retries, duplicate totals, output-limit state, charge-limit state, and accepted charge events.

### Pricing

This Actor uses pay-per-event pricing:

| Event | Price | Charged when |
| --- | ---: | --- |
| `glassdoor-offer` | USD 0.001 per offer (USD 1 per 1,000) | One unique public Glassdoor job offer is written to the default Dataset. |

Duplicate offers, failed searches, and results that are not written do not trigger this event. If the maximum total charge is reached, the Actor stops emitting additional billable items. The current Pricing tab on the Actor page is authoritative.

### API and integrations

Run the Actor through Apify Console, API, CLI, Tasks, Schedules, or webhooks. Dataset results can be exported as JSON, JSONL, CSV, Excel, XML, or RSS.

API request:

```bash
curl -X POST "https://api.apify.com/v2/acts/datascraperes~glassdoor-jobs-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["software engineer"],"country":"usa","maxItemsPerQuery":25,"maxTotalItems":5000,"offset":0,"datePostedHours":0,"jobType":"any","remoteOnly":false,"easyApplyOnly":false,"descriptionFormat":"markdown","includeEmails":false,"location":null}'
```

JavaScript client:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datascraperes/glassdoor-jobs-scraper').call({
  "keywords": [
    "software engineer"
  ],
  "country": "usa",
  "maxItemsPerQuery": 25,
  "maxTotalItems": 5000,
  "offset": 0,
  "datePostedHours": 0,
  "jobType": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "descriptionFormat": "markdown",
  "includeEmails": false,
  "location": null
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datascraperes/glassdoor-jobs-scraper").call(
    run_input={
  "keywords": [
    "software engineer"
  ],
  "country": "usa",
  "maxItemsPerQuery": 25,
  "maxTotalItems": 5000,
  "offset": 0,
  "datePostedHours": 0,
  "jobType": "any",
  "remoteOnly": False,
  "easyApplyOnly": False,
  "descriptionFormat": "markdown",
  "includeEmails": False,
  "location": None
}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Related Actors

| Actor | Best for |
| --- | --- |
| [Indeed Jobs Scraper | Worldwide Job Data](https://apify.com/datascraperes/indeed-jobs-scraper) | Finding worldwide Indeed listings with comparable location, date, job-type, remote, and application filters. |
| [LinkedIn Jobs Scraper – No Login](https://apify.com/datascraperes/linkedin-jobs-scraper) | Adding public LinkedIn job listings with workplace, experience, applicant, and Easy Apply filters. |
| [LinkedIn Company Profile Scraper - No Login](https://apify.com/datascraperes/linkedin-company) | Enriching employers found in job results with public company profiles and organization details. |

### Limits and data quality

- A run accepts up to 50 unique keywords and searches one country site.
- `maxItemsPerQuery` is a ceiling, not a guarantee. Source availability and filters can reduce the number returned.
- The global output limit is 50,000 items, but the user's maximum total charge can stop output earlier.
- Jobs are deduplicated across keywords using stable public identifiers or URLs.
- A run can be `partial` when some keyword searches succeed and others fail; successful Dataset items remain available.
- Listings can change or disappear, and optional salary, description, employer, email, date, location, or application fields can be `null` or empty.
- Remote-only and Glassdoor application filters depend on the public labels available for each listing.
- The Actor does not access private accounts, applications, or information behind a login.

### Frequently asked questions

#### Can I search several countries in one run?

No. Use one country per run and create separate Tasks or runs for additional countries.

#### Why did I receive fewer jobs than requested?

The requested values are maximums. The source may expose fewer matching public listings, and filters, duplicates, output limits, or a maximum charge can reduce the total.

#### Are duplicate jobs charged more than once?

No. Only unique offers actually written to the Dataset trigger `glassdoor-offer`.

#### Can I receive plain text instead of Markdown?

Yes. Set `descriptionFormat` to `plain`; use `html` to preserve HTML instead.

#### Does the Actor always return salaries and direct application links?

No. Those fields are returned only when published and available for the individual listing.

#### Can I schedule recurring searches?

Yes. Save the input as an Apify Task and connect it to an Apify Schedule.

### Responsible use

Use the Actor only for lawful processing of public job information. Follow applicable laws, privacy requirements, Glassdoor's terms, and the rights of employers and applicants. Do not use results for spam, harassment, discrimination, or unlawful automated decisions.

### Support

If a run fails or returns unexpected data, open an issue from the Actor page. Include the run URL, non-sensitive input, and expected behavior, but never publish API tokens or other secrets.

# Actor input Schema

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

One job search phrase per item. Duplicate phrases are removed before the run.

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

Glassdoor country site for this run. Use a country supported by Glassdoor, such as usa, uk, canada, australia, germany, france, india, brazil, mexico, or spain.

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

Optional city, region, postal code, or free-text location understood by Glassdoor. Leave empty to search the selected country site without a location constraint.

## `maxItemsPerQuery` (type: `integer`):

Maximum unique jobs collected for each keyword, up to 1,000. This is a limit, not a guaranteed result count. When offset is used, offset plus this value cannot exceed 1,000.

## `maxTotalItems` (type: `integer`):

Global output safety limit across all keywords. The Actor stops scheduling more work once this limit is reached.

## `offset` (type: `integer`):

Skip this many Glassdoor results before writing jobs for every keyword. Use 0 for the first page of results. Offset plus maxItemsPerQuery cannot exceed 1,000.

## `datePostedHours` (type: `integer`):

Return jobs published within this many hours. Use 0 for any age. Glassdoor may return fewer results when this filter is active.

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

Optional Glassdoor job-type filter. Use Any to include all types.

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

Return only jobs whose public Glassdoor location indicates remote work.

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

Return only jobs marked as eligible for Glassdoor application. Glassdoor may return fewer results when this filter is active.

## `descriptionFormat` (type: `string`):

Format for the public job description returned in each Dataset item.

## `includeEmails` (type: `boolean`):

Extract public email addresses from job descriptions. Disabled by default; no email is included unless explicitly enabled.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "country": "usa",
  "location": null,
  "maxItemsPerQuery": 25,
  "maxTotalItems": 5000,
  "offset": 0,
  "datePostedHours": 0,
  "jobType": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "descriptionFormat": "markdown",
  "includeEmails": false
}
```

# Actor output Schema

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

No description

## `summary` (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"
    ],
    "country": "usa",
    "maxItemsPerQuery": 25,
    "maxTotalItems": 5000,
    "offset": 0,
    "datePostedHours": 0,
    "jobType": "any",
    "remoteOnly": false,
    "easyApplyOnly": false,
    "descriptionFormat": "markdown",
    "includeEmails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/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"],
    "country": "usa",
    "maxItemsPerQuery": 25,
    "maxTotalItems": 5000,
    "offset": 0,
    "datePostedHours": 0,
    "jobType": "any",
    "remoteOnly": False,
    "easyApplyOnly": False,
    "descriptionFormat": "markdown",
    "includeEmails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/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"
  ],
  "country": "usa",
  "maxItemsPerQuery": 25,
  "maxTotalItems": 5000,
  "offset": 0,
  "datePostedHours": 0,
  "jobType": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "descriptionFormat": "markdown",
  "includeEmails": false
}' |
apify call datascraperes/glassdoor-jobs-scraper --silent --output-dataset

```

## MCP server setup

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