11 companies with 40+ open roles publish a salary on none of them
I measured pay transparency the way it is usually measured wrong.
Most "salary transparency" numbers you see are computed over postings that have a salary. That tells you nothing about how often companies disclose, because the ones that disclose nothing never enter the sample. So I built the denominator first: read every posting from the public job feeds of 266 companies (18,668 after de-duplication), then counted how many of those carry a pay range.
The result splits two ways.
Same board, opposite behaviour
Board-level rates hide the interesting part. Here is the range within Ashby and Greenhouse, restricted to companies with at least 25 de-duplicated postings:
| Company | Board | With pay / postings | Rate |
|---|---|---|---|
| sentry | ashby | 42/42 | 100% |
| rain | ashby | 37/37 | 100% |
| algolia | greenhouse | 28/28 | 100% |
| klaviyo | greenhouse | 150/154 | 97.4% |
| ramp | ashby | 160/167 | 95.8% |
| plaid | ashby | 129/135 | 95.6% |
And the other end, still publishing something:
| Company | Board | With pay / postings | Rate |
|---|---|---|---|
| supabase | ashby | 1/59 | 1.7% |
| nubank | ashby | 1/97 | 1.0% |
| sumup | greenhouse | 3/344 | 0.9% |
| elevenlabs | ashby | 1/161 | 0.6% |
| gopuff | lever | 1/784 | 0.1% |
Both lists contain companies that are healthy, well-funded and hiring hard. They simply made different decisions about the same field.
Eleven companies publish nothing at all
40+ open postings, zero pay ranges, and this is not a scraping artefact — the field is absent from the feed, which I verified by dumping the raw JSON keys:
| Company | Board | Postings | With pay |
|---|---|---|---|
| datadog | greenhouse | 418 | 0 |
| betterhelp | greenhouse | 154 | 0 |
| notion | ashby | 140 | 0 |
| langchain | ashby | 104 | 0 |
| spotify | lever | 89 | 0 |
| getyourguide | greenhouse | 74 | 0 |
| trading212 | ashby | 53 | 0 |
| mollie | ashby | 51 | 0 |
A board can be perfectly transparent and a company on it can be perfectly opaque. Board-level rates are a property of the company mix, not of the board. That is the single most useful correction to come out of this dataset.
Why the denominator discipline matters
Two numbers from the same crawl:
- Postings that state a range: 8,039
- Postings read: 18,668
If you compute an average over the first number, you are describing the subset that already chose to be transparent. Any comparison built that way — "remote pays 12% less", "engineers at company X earn Y" — inherits the selection. The honest version pins the denominator to everything read, which is why every rate in this post is with pay / all postings and never with pay / 8,039.
The two failure modes I hit while building this, both of which produce plausible-looking numbers:
- Mixing bases. I first computed rates as
CSV rows / board postings, where the numerator was de-duplicated and the denominator was not. One company came out at 105.9% — a value that cannot exist, and which is the only reason I caught it. Same base on both sides, always. - Unit words anywhere in the text. A job description that mentions "hourly" anywhere turned a $210,000 salary into $436,800,000. I now only read the 40 characters after the last number for a per-hour/per-month hint.
The data
The dataset is free and CC BY 4.0: 8,039 postings that state a pay range, from 266 companies across Greenhouse, Ashby, Lever and Workable, normalised to annual USD, with the original local-currency range kept alongside.
If you want the same rows as JSON with salary filters and an incremental "only jobs I have not seen" mode, that runs as a hosted Actor at $0.0015 per row. The CSV above is the free version and always will be.
If you take one thing from this: before you trust any salary statistic, ask what the denominator was. In pay transparency, the denominator is the whole story.