TL;DR

Pay-transparency laws now require salary ranges in job postings across a growing set of US states and cities — Colorado, California, New York State and City, Washington, Hawaii, Illinois, Minnesota, and others — plus the EU Pay Transparency Directive, which member states are transposing ahead of its June 2026 deadline.

The side effect: job boards now publish a large, continuously updated, public salary dataset. No survey, no self-reporting, no paywall.

What it's genuinely good for: tracking how advertised ranges move over time, comparing what different employers advertise for the same title, and going into a negotiation with evidence rather than a feeling.

What it will mislead you about, if you analyse it naively: four structural biases, covered below. The biggest is that a range's midpoint is not a salary, and ranges are often deliberately wide.

ScrapeMaster extracts posting listings into a table without selectors — auto-detecting the repeating pattern, handling pagination, following through to detail pages where the range usually lives — and exports to CSV, XLSX, JSON, or clipboard for Google Sheets. Data stays in your browser.


What the laws actually require

Requirements differ, and the differences shape your data.

JurisdictionBroad requirement
ColoradoPay range and general benefits description in postings
CaliforniaPay scale in postings (employers over a threshold)
New York State & CityGood-faith minimum and maximum
WashingtonPay range plus general benefits
Illinois, Minnesota, Hawaii, MarylandRange disclosure, varying detail
EU DirectivePre-employment pay information; member state transposition ongoing ahead of June 2026

Three consequences for anyone collecting this data:

Coverage is geographic, not universal. A national posting from a company with no covered employees may carry no range. Remote postings are the interesting case — many employers include ranges on remote roles because they might hire into a covered jurisdiction, which is why remote postings are disproportionately well-populated.

"Good faith" is doing a lot of work. The standard is what the employer honestly expects to pay. It's not audited, and enforcement is complaint-driven.

Format is unregulated. Annual, hourly, monthly. With or without bonus and equity. "$120,000–$180,000" or "$120K-180K" or "120000.00 - 180000.00". Your parsing has to handle all of it.


Collecting it

Where the range lives

Usually on the detail page, not the listing card. Listing cards show title, company, location, and date; the compensation section is inside.

This makes "follow detail pages" the essential feature rather than a nice-to-have. ScrapeMaster's detail-follow opens each posting's link in a background tab, extracts the fields you've defined, and merges them into the main table.

A schema that survives contact with reality

Decide before you start. Retrofitting columns across a dataset you've already collected is the miserable part.

company
job_title
location
remote_status          (onsite / hybrid / remote)
salary_min
salary_max
salary_currency
salary_period          (year / hour / month)
posting_date
captured_date
source_url
seniority              (derive later)
raw_compensation_text  (keep the original string)

raw_compensation_text is the field people leave out and regret. Parsing is lossy and your parser will be wrong about something. Keeping the original string means you can re-parse later without re-collecting.

captured_date matters because postings get edited. The range you saw in August may not be what's there in October.

Pagination and pacing

Job boards paginate heavily — next-page buttons, load-more buttons, numbered pages, infinite scroll. ScrapeMaster auto-detects these patterns and extracts page by page with progress shown.

On pacing: job boards are among the more aggressively bot-protected sites on the web. ScrapeMaster uses your normal browser session and paces naturally, and you can configure extraction delays. It does not rotate proxies or fingerprints, so if a site decides to challenge you, you'll be challenged — which is the correct behaviour, not a limitation to engineer around. Set a delay, collect less per session, run more sessions.

On terms: most job boards' terms restrict automated extraction, and if you have an account you clicked through them. Public postings viewed logged-out sit on considerably firmer ground than anything behind a login. We wrote up how to check this properly in how to read a site's robots.txt and automated-access terms.

Company career pages are the underrated source. Less protected, no intermediary, and the posting is authoritative rather than syndicated. Slower per-company, better data.


The four biases

This is where naive analysis goes wrong, and it goes wrong in a consistent direction.

1. The range is not a salary

A posting saying $120,000–$180,000 does not mean the midpoint is typical. Employers commonly set wide ranges to preserve negotiating room and cover several levels within one posting.

Analyse the minimum and maximum separately. The minimum is closer to a floor for the least experienced acceptable candidate; the maximum is aspirational and frequently reserved for someone who exceeds the posted requirements. The midpoint is an artefact of arithmetic, not a market rate.

Range width itself is a signal. A $60K spread on a mid-level role usually means the posting covers multiple levels, or the employer is keeping options open. A $15K spread signals a defined band.

2. Advertised is not paid

These are ranges for open roles. They tell you what employers are willing to advertise, which is a leading indicator — and it systematically differs from what current employees earn.

Advertised ranges tend to run ahead of internal pay, because hiring markets move faster than internal review cycles. That's exactly why the data is useful for negotiation, and exactly why it's not a measure of current compensation.

3. Geographic and coverage bias

Only postings from covered jurisdictions carry ranges. Collect nationally and you're disproportionately sampling California, New York, Washington, Colorado, and remote roles.

If you compare "roles with ranges" against "all roles", you're comparing high-cost-of-living markets against everywhere, and you'll conclude salaries are higher than they are.

Filter to a jurisdiction, or model location explicitly.

4. Survivorship and staleness

Postings that fill fast disappear fast. A snapshot over-represents roles that stay open — which skews toward hard-to-fill or unattractive positions.

The fix is longitudinal collection. Weekly captures of the same searches let you see what appeared and disappeared, which is more informative than any single snapshot. It also lets you measure time-to-fill by proxy, which nobody publishes.


What the data is good for

Negotiation

The strongest use, and it's concrete.

Collect 20–40 current postings for your title, your seniority, your metro. Filter to companies of comparable size. Look at the distribution of minimums and maximums separately.

Walking in with "I've looked at 34 current postings for this role in this market; the range floors cluster around $X and the ceilings around $Y" is a different conversation from "I feel underpaid." It's public data, it's current, and it's checkable.

Keep dated PDFs of the specific postings you cite. Postings get taken down, and a link that 404s during a salary conversation is worse than no link. Convert: Web to PDF captures each posting as a dated PDF with selectable text, locally.

Compensation benchmarking

For people who set pay rather than receive it: this is a real-time complement to survey data, which is typically six to twelve months stale by publication.

The right use is directional — is the market moving, and how fast — rather than a replacement for a proper survey with matched job architecture.

Market and hiring intelligence

Range movement over quarters shows where competition is intensifying. Which companies post the widest ranges, which pay above their size band, which quietly reduced ranges after a difficult quarter.

Combined with the layoff environment — 2026 has seen thousands of WARN notices filed, though at a lower rate than 2025 — advertised ranges are a useful counterweight to headline narratives. Contraction in one segment can coexist with rising ranges in another.

Career planning

Compare adjacent titles, or the same title in adjacent industries. The premium for a specific skill shows up in range differences long before it shows up in any survey.


Analysis notes

Normalise everything to one period. Hourly to annual at 2,080 hours unless you know otherwise. Keep the original in raw_compensation_text.

Group by seniority, not just title. "Software Engineer" spans a factor of three. Derive seniority from the posting text — years of experience required, level indicators — rather than trusting the title.

Use medians, not means. A handful of executive postings will drag a mean somewhere unhelpful.

Report your n. Twelve postings is an anecdote. Two hundred is a dataset.

Watch for reposts. The same role posted across four boards is one data point, not four. Deduplicate on company plus title plus location plus approximate posting date.


Tool comparison

ScrapeMasterOctoparse / ParseHubWeb Scraper.ioPaid salary data
SetupAuto-detect, secondsVisual builderSitemap configNone
Follows detail pagesYesYesYes
Scheduled runsNoYesCloud tierContinuous
Where data livesYour browserOften cloudLocal / cloudVendor
CostFreePaid tiersFree + paidSubscription
FreshnessWhat you collectScheduledScheduledVaries
Job architecture matchingYou do itYou do itYou do itIncluded

Honest positioning: if you need continuous unattended collection across many boards, a hosted platform or a data vendor is the right category. If you need a few hundred current postings for a negotiation, a benchmark sanity-check, or a research question, a browser extension gets you there this afternoon for nothing.


Frequently asked questions

The postings are published publicly and pay ranges are disclosed because the law requires it, so the data itself is about as public as data gets. The constraints are practical and contractual: most job boards' terms restrict automated extraction, and if you have an account you accepted those terms via clickwrap. Public postings viewed logged-out, collected at browsing pace without bypassing any access control, sits on much firmer ground than anything behind a login.

Why do so many postings have no salary range?

Pay-transparency requirements are jurisdictional. A posting from an employer with no covered employees, for a role in a state without disclosure requirements, carries no obligation. Remote postings are disproportionately likely to include a range because the employer might hire into a covered jurisdiction — which is worth knowing, since it biases any national sample.

Can I trust the ranges to reflect what's actually paid?

Treat them as advertised ranges for open roles, not as measured compensation. Ranges are often deliberately wide to preserve negotiating room and cover multiple levels. Analyse minimums and maximums separately rather than taking midpoints, and remember that advertised ranges tend to run ahead of what current employees earn, because hiring markets move faster than internal review cycles.

Where is the salary range usually found on a job board?

Almost always on the posting's detail page rather than the listing card, which typically shows only title, company, location, and date. This makes detail-page following essential — ScrapeMaster opens each posting's link in a background tab, extracts your defined fields, and merges them back into the main table.

How many postings do I need for a useful comparison?

For a negotiation, 20–40 current postings matched on title, seniority, and metro is enough to state a defensible range. For anything you'd present as analysis, aim for a few hundred and report your sample size. Twelve postings is an anecdote, and treating it as a dataset is how people talk themselves into wrong conclusions.

Will scraping job boards get me blocked?

It can — job boards are among the more aggressively bot-protected sites on the web. ScrapeMaster uses your normal browser session and paces requests naturally, and you can configure extraction delays, but it doesn't rotate proxies or fingerprints. Collect less per session with a delay configured, and prefer company career pages where possible: less protected, and the posting is authoritative rather than syndicated.

How do I keep a record of a posting I want to cite later?

Convert it to PDF at the time you collect it. Postings are removed as soon as roles fill, and a dead link cited in a compensation conversation is worse than no citation. A local browser-based conversion produces a dated PDF with selectable text and keeps it on your machine.


Bottom line

Pay-transparency laws created a public salary dataset as a side effect, and it's genuinely useful — current, free, and checkable in a way survey data isn't.

Collect it properly: get the ranges from detail pages, keep the raw compensation string alongside your parsed values, record the capture date, and collect longitudinally rather than in one snapshot.

Then respect the four biases. The range is not a salary and the midpoint is arithmetic. Advertised is not paid. Coverage is geographic, so a national sample is really a sample of a few expensive states. And postings that linger are over-represented in any snapshot.

Get those right and you can walk into a compensation conversation with thirty-four current postings and a defensible number. That's a materially better position than most people ever occupy.

ScrapeMaster is free, has no row limits, follows detail pages, and keeps your data in your browser. Pair it with Convert: Web to PDF to keep dated copies of the postings you plan to cite.

Also from us: CineMan AI, for evenings that shouldn't involve spreadsheets.