levels.fyi Salary Scraper — Tech Compensation & Salary Data API avatar

levels.fyi Salary Scraper — Tech Compensation & Salary Data API

Pricing

from $4.00 / 1,000 salary records

Go to Apify Store
levels.fyi Salary Scraper — Tech Compensation & Salary Data API

levels.fyi Salary Scraper — Tech Compensation & Salary Data API

Scrape tech compensation data from levels.fyi: base salary, stock, bonus, and total compensation by company, job family, level, and location. Per-offer records or aggregated percentile bands.

Pricing

from $4.00 / 1,000 salary records

Rating

0.0

(0)

Developer

bootforge

bootforge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

levels.fyi Salary Scraper — Tech Compensation Data

levels.fyi Salary Scraper is an Apify actor that extracts tech compensation data from levels.fyi — per-offer salary records and per-level aggregate/percentile bands — by company, job family, and location.

Use it to benchmark comp bands before a negotiation, build a compensation-intelligence dashboard, track how a company's pay moves over time, or feed a recruiting/market-research pipeline — exported to JSON, CSV, or Excel.

Table of contents

What the levels.fyi Salary Scraper does

  • 💰 Per-offer records — individual self-reported comp entries: base, stock, bonus, total compensation, title, years of experience, and location.
  • 📊 Per-level aggregates — company/level rollups with percentile bands (p10–p90) for total compensation and base salary, plus sample count.
  • 🏢 Company + job family targeting — pass explicit company slugs (google, meta) and a job family (software-engineer, product-manager, data-scientist), or enable Discover all companies to enumerate the whole levels.fyi company index.
  • 🌍 Location filters — narrow to specific levels.fyi location slugs (united-states, india), or leave empty for the default all-location view.
  • HTTP-only, no anti-bot — no login, no CAPTCHA, no browser tier; runs are fast and proxy is optional.

How to scrape levels.fyi salary data

  1. Click Try for free and open the actor.
  2. Enter one or more companies (slugs like google, meta) or turn on discover_all to enumerate every company on levels.fyi.
  3. Set job_family (defaults to software-engineer) and, optionally, locations.
  4. Choose modeone per run: records (one row per individual offer, the default) or aggregates (one summary row per level: averages + percentile bands). Each mode yields a clean single-schema dataset; run twice if you want both.
  5. Click Start and watch results stream into the dataset.
  6. Export as JSON, CSV, or Excel, or pull from the Apify API.

Individual salary records for two companies (the default):

{
"companies": ["google", "meta"],
"job_family": "software-engineer",
"mode": "records"
}

Aggregated salary bands only, capped discovery run across the whole company index:

{
"discover_all": true,
"max_companies": 50,
"mode": "aggregates"
}

levels.fyi scraper input

FieldTypeDefaultDescription
companiesstring[]Company names or levels.fyi slugs (e.g. google, Meta — auto-slugified). Provide this or enable discover_all.
job_familystringsoftware-engineerlevels.fyi job-family slug, e.g. software-engineer, product-manager, data-scientist.
locationsstring[]Optional levels.fyi location slugs for metro-specific pay. Empty = nationwide. See Locations for common slugs.
modeenumrecordsOne per run. records = one row per individual offer; aggregates = one summary row per level (averages + percentile bands). Never mixed, so each run's dataset has a single clean schema.
discover_allbooleanfalseEnumerate every company on levels.fyi (ignores companies). Use max_companies to cap.
max_companiesintCap on how many companies to enumerate when discover_all is on.
max_recordsintCap on per-offer salary records per company/location.
transportenumautoHTTP engine: auto (curl_cffi), curl_cffi, httpx, or primp.
proxyobjectOptional Apify Proxy configuration. Not required for correctness — see Recommended proxies.

Locations

Compensation varies widely by metro (SF Bay Area vs. the rest of the US can differ by tens of thousands). Pass one or more locations slugs to scrape metro- or country-specific pay; each is scraped separately and the location_name output field tells you which one a row belongs to. Leave locations empty for nationwide numbers.

Common US metros: san-francisco-bay-area, greater-seattle-area, new-york-city-area, greater-los-angeles-area, greater-boston-area, greater-chicago-area, greater-austin-area, greater-dallas-area, greater-houston-area, atlanta-area, greater-san-diego-area, raleigh-durham-area, greater-detroit-area, philadelphia-area, phoenix-area

Countries: united-states, india, united-kingdom, canada, germany, netherlands, ireland, australia, singapore, israel, france, switzerland, poland, japan, brazil, mexico, spain, sweden

Any other location: open it on levels.fyi and copy the last path segment of the URL — …/salaries/software-engineer/locations/<slug>.

What data you get

Aggregated salary bands (mode: aggregates)

One summary row per company/level. Sample from a live run (Google, L3, software-engineer, United States):

{
"company": "Google",
"level": "l3",
"job_family": "software-engineer",
"level_name": "L3",
"scraped_at": "2026-07-17T07:09:42.077676+00:00",
"count": 33,
"base": 161788,
"stock": 34280,
"bonus": 8702,
"total": 204770,
"tc_p10": 176000,
"tc_p25": 208000,
"tc_p50": 293000,
"tc_p75": 403000,
"tc_p90": 486500,
"base_p10": 151000,
"base_p25": 168000,
"base_p50": 200000,
"base_p75": 218000,
"base_p90": 242000,
"location_name": "United States"
}
FieldDescription
company, level, job_familyCompany name, level identifier, and job family the aggregate covers.
countNumber of self-reported data points behind this rollup.
base, stock, bonus, totalAverage annual base salary, stock grant value, bonus, and total compensation (USD).
tc_p10tc_p90Total-compensation percentile bands where levels.fyi exposes them; unpublished percentiles are null.
base_p10base_p90Base-salary percentile bands, same null-if-unpublished rule.
location_name, scraped_atLocation the aggregate covers and capture timestamp.

Individual salary records (mode: records, default)

One row per self-reported offer. Sample from a live run (Google, L3):

{
"company": "Google",
"level": "L3",
"uuid": "b6e2f5b0-7c9a-4b8e-9d1a-2f6a8c3d5e9f",
"scraped_at": "2026-07-17T09:12:44.118203+00:00",
"title": "Software Engineer",
"job_family": "software-engineer",
"focus_tag": "DevOps",
"years_of_experience": 1,
"years_at_company": null,
"offer_date": null,
"location": "Los Angeles, CA",
"country_id": null,
"dma_id": null,
"base_salary": 140000,
"avg_annual_stock_grant_value": 20000,
"avg_annual_bonus_value": null,
"total_compensation": 160000,
"gender": null
}
FieldDescription
company, level, title, focus_tagCompany, level, job title, and specialization tag (e.g. DevOps) as self-reported.
years_of_experience, years_at_companyReporter's tenure, when disclosed.
locationFree-text city/region as reported.
base_salary, avg_annual_stock_grant_value, avg_annual_bonus_value, total_compensationAnnualized compensation components (USD).
uuid, scraped_atlevels.fyi's own record identifier and capture timestamp.

Pricing

This actor uses pay-per-event pricing — you pay for what you scrape, not for time. Pricing below is provisional until Console monetization is finalized (see the Monetization tab for current live pricing).

EventUSDPer 1,000
Actor start (per run)$0.001
Salary record scraped (salary-record)$0.002$2
Salary aggregate scraped (salary-aggregate)$0.001$1
Typical runCost
1 company, aggregates (~7 levels)~$0.008
1 company, records (~50 offers)~$0.101
10 companies, records (~500 offers)~$1.001

Proxy is optional. levels.fyi's public salary pages are server-rendered and require no login or CAPTCHA, so a proxy is not required for correctness — only useful for scale (avoiding shared-IP rate limits on large discover_all runs).

If you run your own scrapers (inside or outside Apify) and need reliable proxies for scale, we use DataImpulse — pay-as-you-go IPs with per-country targeting and no monthly minimum:

👉 Get DataImpulse proxies (referral link)

Why this levels.fyi scraper

  • No anti-bot tax — HTTP-only, no browser, no CAPTCHA solving; runs are fast and cheap because levels.fyi's public salary pages need none of that.
  • Two granularities, one actor — per-offer records for the raw distribution, or per-level aggregates with percentile bands; pick one per run for a clean single-schema dataset.
  • Company discovery built indiscover_all enumerates the full levels.fyi company index instead of requiring you to hand-curate slugs.
  • Validated output — every row is Pydantic-validated before it's pushed; malformed entries are dropped, not shipped with garbage fields.
  • Open source — the underlying levels-fyi-scraper Python package ships a Typer CLI and a FastAPI server; the Apify wrapper is a thin layer.

FAQ

What's the difference between records and aggregates? Records are individual self-reported offers (one row per person) — pick this (the default) for the raw, granular data. Aggregates are per-level rollups levels.fyi computes from those same reports — one row per level with averages plus percentile bands — pick this for quick benchmarking. You choose one mode per run so each dataset stays a single clean schema; run the actor twice if you want both.

Do I need a proxy? No. levels.fyi's public salary pages have no known anti-bot layer, so a proxy is optional. It only helps at scale on large discover_all runs. For your own scrapers, we recommend DataImpulse.

Why are some percentile fields null? levels.fyi doesn't publish every percentile band (p10/p25/p75, etc.) for every company/level/location combination — only the bands it actually surfaces are populated; the rest are null rather than guessed.

What does discover_all do, and how do I limit it? It ignores companies and enumerates every company slug on levels.fyi's public index instead. Set max_companies to cap how many it processes — useful to control run cost and duration.

Can I scrape multiple job families or locations in one run? One job_family per run by design (it's part of the URL levels.fyi serves). locations accepts multiple slugs, and each is fetched per company.

Is scraping levels.fyi legal? This actor collects only publicly available, aggregated and self-reported compensation data. You are responsible for complying with levels.fyi's terms and applicable laws. Do not use this data to identify or target individual reporters.

Rate this actor ⭐

If the levels.fyi Salary Scraper saved you time, please leave a review on its Apify Store page — ratings help other people find it and tell us what to build next. Hit a bug or missing field? Open an issue or contact us through the actor's Issues tab and we'll fix it fast — recency and reliability are what keep this actor ranking.

Building a compensation or hiring-intelligence pipeline? Pair this actor with our other scrapers — same proxy config format, same Pydantic-validated output, all open source.