Skip to main content
Thirdwatchthirdwatch
Hiring & talent

Track Glassdoor Review Rating Changes Over Time (2026)

Store Glassdoor review snapshots, compare sampled review ratings, and avoid confusing a sample mean with the company headline rating.

Editorial illustration for hiring & talent
Apr 27, 2026 · 3 min read · 628 words
View the Apify scraper →

The Thirdwatch Glassdoor Scraper can collect review records for a company query. Saving repeated snapshots lets you compare the reviews returned by each run. It does not return an official company-rating history.

The current review output uses company, rating, title, pros, cons, date and employee_status. It does not expose the company_rating, reviews_count, CEO approval or recommendation percentages used in an earlier version of this guide. Build the comparison around the fields actually returned.

Collect one small review snapshot first

Direct Actor runs use your Apify account and the current Actor pricing. Begin with one company and inspect the returned records before scheduling a peer set.

{
  "queries": ["stripe"],
  "scrapeType": "reviews",
  "country": "us",
  "maxResults": 5
}

maxResults applies separately to each query. The example above uses one query with a cap of five reviews. With 20 queries and maxResults: 50, the run can return up to 1,000 reviews; source availability can reduce that count. Before adding queries or schedules, budget for the query count multiplied by the cap and the current Actor pricing. This setting limits records, not monetary spend.

Save the records with a collection timestamp

import os
import json
from datetime import datetime, timezone
from pathlib import Path
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("thirdwatch/glassdoor-scraper").call(
    run_input={
        "queries": ["stripe"],
        "scrapeType": "reviews",
        "country": "us",
        "maxResults": 5,
    }
)
records = list(client.dataset(run["defaultDatasetId"]).iterate_items())
collected_at = datetime.now(timezone.utc).isoformat()
folder = Path("snapshots")
folder.mkdir(exist_ok=True)
filename = datetime.now(timezone.utc).strftime("glassdoor-%Y%m%dT%H%M%SZ.json")
(folder / filename).write_text(json.dumps({
    "collected_at": collected_at,
    "dataset_id": run["defaultDatasetId"],
    "records": records,
}))
print(f"Saved {len(records)} review records.")

The collection timestamp is when your run observed the page; the review's date is source text and may be missing or use a localized format. Keep both rather than substituting one for the other.

Compute a sample rating summary

This example summarizes one returned sample. Ratings are strings in the extractor, so convert them to numbers and exclude unavailable ratings. Missing columns are handled explicitly.

import pandas as pd

frame = pd.DataFrame(records).reindex(
    columns=["company", "rating", "title", "pros", "cons", "date"]
)
frame["rating"] = pd.to_numeric(frame["rating"], errors="coerce")
rated = frame.dropna(subset=["company", "rating"]).drop_duplicates(
    subset=["company", "title", "date", "pros", "cons"]
)
summary = rated.groupby("company").agg(
    sample_mean_rating=("rating", "mean"),
    rated_reviews_in_sample=("rating", "size"),
).reset_index()
summary["collected_at"] = collected_at
print(summary)

The content-based deduplication above is a heuristic, not a stable review identifier: similar titles or missing dates can collapse distinct reviews. Inspect collisions before using it on larger samples.

Save summaries from comparable runs and calculate the difference between their sample_mean_rating values. Also display rated_reviews_in_sample. Do not label that count as the company's total review count or present the sample mean as Glassdoor's headline rating.

Decide what a change can tell you

Differences can come from newly returned reviews, repeated reviews, a changed search result, extraction gaps or missing dates. A numeric decline alone does not demonstrate a culture problem or predict employee attrition. Review the underlying records and collection coverage before drawing a conclusion.

Use a repeatable query, country and cap for each company. If a run fails or returns nothing, record the gap rather than entering a zero rating. If names change or multiple company entries match, resolve the entity before combining the snapshots.

Schedule collection after validating coverage

Apify schedules can repeat the same Actor input. Start with a collection interval suited to your reporting needs and inspect the first repeated snapshots. The Actor does not create a Slack alert or a historical dataset for you; those are separate operations in your own pipeline.

For a one-off company research question, see the Thirdwatch company research workflow and use only the MCP sources it advertises. Repeated collection and longitudinal analysis still require saved snapshots; a current MCP result does not establish a historical trend.

Frequently asked questions

Does this actor return a company-wide rating history?

No. Review mode returns individual review records. The current schema does not provide company_rating, reviews_count, CEO approval or an official historical company-rating series.

Can I compare ratings across snapshots?

Yes, after checking company identity, deduplicating reviews and recording sample counts. A mean of returned review ratings describes that sample; it is not Glassdoor's company headline rating.

What alert threshold should I use?

Choose a threshold for your own sample and validate it over time. A rating change alone does not establish attrition risk, a culture problem or statistical significance.

Related