Glassdoor Jobs Scraper & API - Salary Data avatar

Glassdoor Jobs Scraper & API - Salary Data

Pricing

from $1.00 / 1,000 glassdoor job results

Go to Apify Store
Glassdoor Jobs Scraper & API - Salary Data

Glassdoor Jobs Scraper & API - Salary Data

Scrape Glassdoor jobs by keyword, free-text location, company page, or bulk URLs. Export salaries, ratings, posting age, Easy Apply, descriptions, and new-job monitoring data.

Pricing

from $1.00 / 1,000 glassdoor job results

Rating

0.0

(0)

Developer

Newbs

Newbs

Maintained by Community

Actor stats

7

Bookmarked

150

Total users

2

Monthly active users

a day ago

Last modified

Share

Scrape public Glassdoor job listings by keyword, free-text location, search URL, or company jobs page. Export stable job IDs, salaries, posting age, Easy Apply status, employer ratings, logos, descriptions when available, and monitoring metadata to JSON, CSV, Excel, APIs, MCP, or Apify integrations.

The Actor tries a lightweight HTTP request with browser TLS impersonation before starting Chrome. It parses rich metadata from Glassdoor's search payload, so useful rows remain available even when protected job-detail pages do not expose full descriptions.

Glassdoor Scraper Features

  • Search by role, skill, company, city, region, or country
  • Resolve free-text locations with Glassdoor's public location lookup
  • Paste /Job/ search URLs or /Jobs/ company pages
  • Run up to 10 keyword, location, or URL searches in one Actor run
  • Deduplicate all results by stable Glassdoor job ID
  • Export flat integration-ready fields and the previous nested output objects
  • Collect posting age, estimated posting date, Easy Apply, sponsorship, remote status, employer rating, logo, normalized title, and salary source
  • Export typed salary minimum, median, maximum, currency, and pay period when published
  • Filter by age, remote status, Easy Apply, sponsorship, rating, salary, company, and job type
  • Optionally try protected detail pages for full descriptions and JobPosting data
  • Track first-seen, last-seen, and repeat observations across scheduled runs
  • Return only new job IDs for alerts and recurring monitoring
  • Apply optional result and field-coverage gates for production workflows
  • Respect maxItems and Apify pay-per-event spending limits before writing rows

Quick Start

  1. Enter a job keyword such as software engineer.
  2. Enter a location such as London, Berlin, Germany, or united-kingdom.
  3. Set the maximum number of unique results.
  4. Keep Try full descriptions enabled when descriptions matter, or disable it for the fastest and most reliable search-metadata run.
  5. Click Start and open the Dataset tab.
{
"job": "software engineer",
"location": "united-kingdom",
"maxItems": 25,
"includeDetails": false,
"proxy": {
"useApifyProxy": true
}
}

Input

FieldDefaultDescription
jobsoftware engineerJob title, skill, keyword, or company for the guided search.
locationunited-kingdomFree-text city, region, state, or country.
countryCodeemptyOptional two-letter country code used to choose a regional Glassdoor domain.
searchUrlemptyOptional public Glassdoor search or company jobs URL.
searches[]Up to 10 bulk search objects. Replaces the single guided search when supplied.
numberOfPages1Maximum result batches per search when browser pagination is required.
maxItems10Global unique-row limit after filters and deduplication.
sortByrelevancerelevance, glassdoor, date, or salary.
postedWithinDays0Maximum listing age. Zero disables the filter.
remoteOnlyfalseKeep only listings identified as remote.
easyApplyOnlyfalseKeep only Glassdoor Easy Apply listings.
includeSponsoredtrueDisable to remove sponsored listings.
minCompanyRating0Minimum Glassdoor employer rating.
minSalary / maxSalary0Numeric salary-range filters without currency or period conversion.
companyemptyCase-insensitive company-name substring.
jobTypeemptyEmployment-type substring such as full, contract, or internship.
includeDetailstrueTry detail pages for complete descriptions and structured JobPosting data.
detailConcurrency3Concurrent detail-page workers, from 1 to 5.
monitoringEnabledfalsePersist first-seen and repeat-observation state.
onlyNewJobsfalseWrite and charge only previously unseen job IDs. Also enables monitoring.
monitoringKeyemptyStable name for a scheduled monitoring stream.
monitoringRetentionDays90Forget IDs not observed during this period.
qualityChecks{}Optional minimum results, successful searches, and field-coverage thresholds.
proxyautomaticDirect-first routing with proxy fallback; explicit settings are honored.

Bulk Glassdoor Searches

Use searches to combine roles, markets, and company pages. Duplicate job IDs are merged into one dataset row, with every matching search retained in matchedSearches.

{
"searches": [
{
"label": "UK backend",
"job": "backend engineer",
"location": "United Kingdom",
"countryCode": "GB"
},
{
"label": "Berlin data",
"job": "data engineer",
"location": "Berlin, Germany",
"countryCode": "DE",
"sortBy": "date"
},
{
"label": "Company jobs",
"searchUrl": "https://www.glassdoor.com/Jobs/Google-Jobs-E9079.htm"
}
],
"maxItems": 100,
"includeDetails": false
}

Custom URLs preserve Glassdoor's order by default. Enable rankCustomUrlResults globally, or rankByKeyword on one bulk entry, only when its job keyword should intentionally reorder the pasted URL.

Filters

Filters use structured search metadata and run before rows are written. A listing with missing metadata is excluded when a filter requires that metadata. For example, postedWithinDays: 7 excludes rows where Glassdoor did not publish a posting age.

{
"job": "software engineer",
"location": "London",
"countryCode": "GB",
"postedWithinDays": 7,
"remoteOnly": true,
"includeSponsored": false,
"minCompanyRating": 4,
"minSalary": 70000,
"maxItems": 50,
"includeDetails": false
}

Salary filters compare the published numeric values without converting currency or pay period. Do not compare hourly and annual values in the same filtered run unless that is intentional.

New Job Monitoring

Enable monitoring on an Apify schedule to maintain state for one search configuration. onlyNewJobs writes only IDs that were not committed by earlier successful runs, which makes datasets and webhooks suitable for alerts.

{
"job": "mobile engineer",
"location": "United Kingdom",
"countryCode": "GB",
"postedWithinDays": 7,
"monitoringEnabled": true,
"onlyNewJobs": true,
"monitoringKey": "uk-mobile-engineering-daily",
"monitoringRetentionDays": 90,
"includeDetails": false,
"maxItems": 100
}

Monitoring adds:

  • firstSeenAt: first committed observation of this job ID
  • lastSeenAt: timestamp of the current observation
  • isNew: whether the ID was absent from monitoring state
  • seenCount: number of monitored runs that observed the ID

Avoid overlapping runs with the same monitoring key. New IDs are committed only after their dataset rows are successfully written, so spending-limit skips are not incorrectly marked as delivered.

Output

The Jobs dataset view uses flat fields for integrations and exports. Full details includes search provenance and enrichment diagnostics. Monitoring focuses on new and repeat observations. The existing jobDescription, employerOverview, and employerBenefits objects remain in every row for backward compatibility.

{
"jobId": "1010147260845",
"title": "Software Engineer",
"normalizedTitle": "software engineer",
"company": "Example Ltd",
"companyId": "12345",
"companyRating": 4.2,
"companyLogoUrl": "https://media.glassdoor.com/example.png",
"location": "London, England",
"ageInDays": 2,
"estimatedDatePosted": "2026-08-30",
"easyApply": false,
"isSponsored": false,
"isRemote": false,
"salary": "GBP 65000 - 90000",
"salaryMin": 65000,
"salaryMedian": 78000,
"salaryMax": 90000,
"salaryCurrency": "GBP",
"salaryPeriod": "YEAR",
"salarySource": "EMPLOYER_PROVIDED",
"jobUrl": "https://www.glassdoor.co.uk/job-listing/example.htm?jl=1010147260845",
"source": "search_result",
"enrichmentStatus": "not_requested",
"firstSeenAt": "",
"lastSeenAt": "",
"isNew": false,
"seenCount": 0
}

estimatedDatePosted is derived from Glassdoor's published ageInDays. It is deliberately separate from the exact datePosted field returned by JobPosting structured data.

Fast Search or Full Descriptions

ModeBest forBehavior
includeDetails: falseMonitoring, salary analysis, lead lists, bulk searchesHTTP-first search metadata with browser fallback only when required
includeDetails: trueDescription and requirements analysisRich search metadata plus best-effort protected detail pages

Glassdoor can expose a job search card while protecting its detail page. In that case, the Actor keeps the rich search row and sets enrichmentStatus to blocked, navigation_failed, unavailable, parse_failed, or budget_exhausted. It does not discard the job or fabricate a description.

Production Quality Checks

Scheduled workflows can fail before writing rows when live quality falls below explicit thresholds.

{
"qualityChecks": {
"minimumResults": 3,
"minimumSuccessfulSearches": 2,
"minimumCoreFieldCoverage": 0.95,
"minimumMetadataCoverage": 0.5
}
}

Core coverage measures job ID, title, company, location, and URL. Metadata coverage measures posting age, Easy Apply, rating, logo, and salary source. A failed gate writes diagnostics to OUTPUT and fails before dataset-result events are emitted.

API and Integrations

Run the Actor from the Apify API, JavaScript or Python clients, CLI, MCP, schedules, webhooks, Make, Zapier, Google Sheets, or another Apify integration.

curl -X POST \
"https://api.apify.com/v2/acts/newbs~Glassdoor-Job-Scraper/runs?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"job":"data engineer","location":"Berlin, Germany","countryCode":"DE","maxItems":25,"includeDetails":false}'

Each run writes OUTPUT with status, duration, routes attempted, per-search results, duplicate count, enrichment totals, monitoring statistics, and quality coverage.

Pricing

The Actor charge remains $0.01 per run start plus $0.001 per job result. A run returning 100 jobs has an Actor charge of $0.11. Apify platform usage, including compute, storage, and proxy transfer, is billed separately by Apify according to the user's plan.

Rows filtered out, duplicate IDs, repeated jobs removed by onlyNewJobs, blocked zero-result runs, and quality-gate failures do not emit dataset-result events. Use maxItems and Apify spending limits to bound charges.

Reliability and Performance

The Actor first tries HTTP with browser TLS impersonation. If Glassdoor blocks or changes that response, it falls back to the existing Chrome extraction path. Both paths use the same structured payload parser and output contract.

Search metadata is parsed from rendered cards and embedded Glassdoor jobview objects. The Actor stops paging after enough filtered candidates are available, opens a circuit after protected detail responses, honors the run's actual Apify timeout, reserves time for dataset and OUTPUT writes, and merges tracking-URL variants by stable job ID.

Automatic routing starts direct to reduce latency and proxy transfer, then tries the automatic Apify Proxy with a fresh-session retry and a location-matched Residential session only when earlier routes are blocked. Apify Unblocker is the final HTTP fallback before Chrome and can add separately billed platform usage. Explicit proxy groups and custom proxy URLs are used exactly as configured. Proxy credentials, custom URLs, challenge tokens, page body text, and runner IP addresses are excluded from logs.

FAQ

Why is a description empty?

The search response was available but the protected detail page did not expose JobPosting data. Use enrichmentStatus and enrichmentFailureReason to distinguish blocked, unavailable, and budget-limited details.

What timeout should a scheduled bulk search use?

The default 120-second timeout supports small fast-mode bulk searches. Network routes use bounded attempts and reserve time for quality diagnostics and OUTPUT. Increase the timeout only for larger page counts, many searches, or detail enrichment, where the requested work itself needs more time.

Why is datePosted empty while estimatedDatePosted has a value?

Glassdoor published a posting age but not an exact date. The Actor keeps derived dates explicitly labeled as estimates.

Why did a filtered run return fewer jobs?

Filters exclude rows that do not publish the required metadata. Glassdoor may also expose fewer unique listings than maxItems or stop returning new jobs during pagination.

Can I scrape a location that is not preconfigured?

Yes. Enter free text and optionally a two-letter country code. The Actor attempts Glassdoor's location lookup and falls back to the public search slug. A copied Glassdoor search URL remains the most exact way to preserve complex filters.

Why did a monitored run return zero rows?

When the search succeeds and onlyNewJobs is enabled, zero rows normally means every discovered job ID was already recorded. Check OUTPUT.monitoring.existingCount to distinguish this from source blocking.

Responsible Use

Use the Actor responsibly and only for lawful purposes. Ensure that your collection, storage, and use of data comply with applicable laws, Glassdoor terms, privacy requirements, and Apify policies.