Use cases / Glassdoor API
Salary benchmarking
Last updated September 28, 2026. Response excerpts are recorded from the live API.
Who
Who runs this, and what for
| Team | What they decide with it |
|---|---|
| Recruiters and talent teams | Whether an offer is competitive against the companies the candidate is also talking to. |
| Compensation teams | Where to set a band for a new role, and which roles have drifted below market. |
| HR and people analytics products | What market pay to show customers next to their own payroll data. |
Pipeline
The calls, step by step
01Find each employer's id
Company search takes a name and returns employer_id and slug, with the company's rating and how many salaries it has. Both ids are needed for every salary call, and they do not change, so store them.
GET /v1/company/search?engine=glassdoor&q=stripe · results.0
{ "position": 1, "employer_id": "671932", "name": "Stripe", "slug": "Stripe", "logo": "https://media.glassdoor.com/sql/671932/stripe-squarelogo-1610580619584.png", "rating": 3.8, "reviews_count": 1588, "salaries_count": 4659, "jobs_count": 4, "url": "https://www.glassdoor.com/Overview/Working-at-Stripe-EI_IE671932.11,17.htm" }Recorded response. Live values differ. 02Read pay by job title
Salaries returns ten job titles per page, most-reported first, each with base and total pay at the 10th, 25th, 50th, 75th, and 90th percentiles, the number of reports, and when the last one came in. Page until you have the titles you need; the common titles sit in the first few pages.
GET /v1/company/salaries?engine=glassdoor&employer_id=9079&slug=Google&page=2 · results.0
{ "position": 11, "job_title": "Software Engineer III", "job_title_id": "4514", "salaries_count": 950, "currency": "USD", "period": "year", "base_pay": { "p10": 159325, "p25": 176568, "p50": 197943, "p75": 221906, "p90": 245922 }, "total_pay": { "p10": 271280, "p25": 321338, "p50": 390969, "p75": 492142, "p90": 599160 }, "last_reported_at": "2026-07-24T07:10:52.947Z" }Recorded response. Live values differ. 03Compare with posted pay
Self-reported pay lags the market. Posted ranges on current openings show what employers offer now: Glassdoor job search returns salary with min, max, and whether the employer or Glassdoor supplied it.
GET /v1/search?engine=glassdoor&q=software+engineer&page=1 · results.0.salary
{ "min": 110000, "max": 160000, "median": 135000, "currency": "USD", "period": "year", "source": "employer" }Recorded response. Live values differ.
Code
A script to start from
salary_bands.py
# Salary bands for chosen job titles at the employers you hire against.
# Out: salaries.csv, one row per employer and title, base and total pay.
import csv, os, requests
API = "https://api.clair.im"
HEADERS = {"Authorization": f"Bearer {os.environ['CLAIR_API_KEY']}"}
EMPLOYERS = ["Stripe", "Datadog", "Cloudflare"]
TITLES = {"software engineer", "senior software engineer", "product manager"}
MAX_PAGES = 5 # 10 titles per page, most-reported first
def get(path, **params):
r = requests.get(f"{API}{path}", headers=HEADERS, timeout=90,
params={"engine": "glassdoor", **params})
r.raise_for_status()
return r.json()
with open("salaries.csv", "w", newline="") as f:
out = csv.writer(f)
out.writerow(["employer", "title", "reports", "base_p25", "base_p50",
"base_p75", "total_p50", "last_reported_at"])
for name in EMPLOYERS:
employer = get("/v1/company/search", q=name)["results"][0]
for page in range(1, MAX_PAGES + 1):
body = get("/v1/company/salaries", employer_id=employer["employer_id"],
slug=employer["slug"], page=page)
for row in body["results"]:
if row["job_title"].lower() in TITLES:
b, t = row["base_pay"], row["total_pay"]
out.writerow([employer["name"], row["job_title"], row["salaries_count"],
b["p25"], b["p50"], b["p75"], t["p50"],
row["last_reported_at"]])
if not body["next_cursor"]:
break
Set CLAIR_API_KEY to a key subscribed to the Glassdoor API. Each call is one request against that API's monthly quota.
Cost
What it costs per month
| Schedule | Requests | Plan | Per month | Per 1,000 |
|---|---|---|---|---|
| 10 employers, refreshed monthly10 company searches plus 5 salary pages each = 60 requests. Cache the ids and later months cost 50. | 60 | Pay as you go | $0.47 | $7.83 |
| 50 employers, refreshed monthly50 × (1 search + 5 salary pages) = 300 requests. | 300 | Pay as you go | $2.34 | $7.80 |
| 500 employers, 10 pages each, monthly500 × (1 search + 10 salary pages) = 5,500 requests, for a market-wide benchmark. | 5,500 | Pay as you go | $42.90 | $7.80 |
Limits
What to plan for
- Glassdoor salaries are reported by employees and candidates. Titles with few reports (salaries_count) are noisy; set a minimum before you use a number.
- Pay is for the location the response names, United States in the recorded example, in the currency and period each row states. Do not mix yearly and hourly rows.
- Up to 20 pages of 10 titles per employer. Rare titles at large employers may be past that.
- Job titles are Glassdoor's, not yours. Map them to your own levels once, by hand, and keep the mapping.
FAQ
Common questions
What is the difference between base pay and total pay?
Base is salary. Total pay adds the cash bonus, stock, and profit sharing people reported. At large tech companies total pay can be twice base, so compare like with like.
How current is the data?
Each row has last_reported_at, the date of its most recent report. The percentiles cover reports over a longer window, so they move slowly.
Can I get salaries for a title across all companies?
Not in one call: salaries are read per employer. Read the employers you care about, or use posted ranges from job search for a market-wide view.
Run it on your own products
200 requests a month free on each API, no card. Enough to run the pipeline on a short list before choosing a plan.
Bloomberg News API
Associated Press API
Glassdoor API
Greenhouse Jobs API

Crunchbase API
Website Contacts API