Job Salary Data Scraper: Pay Transparency Jobs Feed
Pricing
from $0.36 / 1,000 results
Job Salary Data Scraper: Pay Transparency Jobs Feed
Job salary data scraper for Greenhouse, Lever and Ashby boards: returns only postings with a disclosed pay range (min, max, currency, period, annual pay, country, remote). Export JSON, CSV, Excel.
Pricing
from $0.36 / 1,000 results
Rating
0.0
(0)
Developer
Alexandre Manguis
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
Job salary data scraper for public Greenhouse, Lever and Ashby company job boards. It returns only postings that disclose a numeric pay range, normalised to min, max, currency and period, plus an annualised min/max/mid so rows are comparable. Export as JSON, CSV, Excel or via the API.
What does it do?
You give it company job boards (for example greenhouse:coinbase, lever:outreach, ashby:ramp, or a public board URL), or switch on the built-in list of 35 boards. The Actor reads the public board APIs and keeps only the postings with a disclosed salary range. Postings without pay data are dropped, so you are never billed for them.
Each row contains the raw range (salaryMin, salaryMax, salaryCurrency, salaryPeriod), annualised values (annualSalaryMin, annualSalaryMax, annualSalaryMid), the range width in percent, a title family, a seniority guess, the country, a remote flag and the job URL.
Who is it for / use cases
- Compensation and HR teams: benchmark advertised pay for a role across competitors.
- Recruiters and sourcers: find companies that publish pay and filter by country, remote or minimum salary.
- Job seekers and career coaches: build a salary-transparent job list.
- Data teams and journalists: track pay-transparency disclosure over time (pay-transparency laws in several US states and the EU push employers to publish ranges).
- Job boards and newsletters: feed a "jobs with salary" section.
Features
- Only postings with a numeric pay range are returned and billed.
- Supports Greenhouse, Lever and Ashby public boards; vendor is auto-detected from a board URL.
- Normalises periods (year, month, hour, ...) to annual figures. No FX conversion: values stay in the posting's own currency.
- Filters: ATS vendor, countries, title keywords, remote only, minimum annual salary, currencies.
- Optional plain-text description (up to 5,000 characters).
- Stops cleanly when your maximum charge for the run is reached.
- Invalid board entries are logged and skipped.
Input
| Field | Type | Description |
|---|---|---|
companies | string list | Boards to scan: greenhouse:stripe, lever:outreach, ashby:ramp or a public board URL. |
useBuiltInSeedList | boolean | Also scan the built-in list (35 boards, limited by maxCompanies). Default false. |
atsSources | list | greenhouse, lever, ashby. Default all three. |
countries | string list | ISO 3166-1 alpha-2 codes (US, GB, DE). Empty = all. |
titleKeywords | string list | Keep titles containing any of these words. |
remoteOnly | boolean | Keep only remote postings. |
minAnnualSalary | integer | Minimum annualised maximum, in the posting's own currency. |
currencies | string list | ISO 4217 codes (USD, EUR). Empty = all. |
maxResults | integer | Stop after this many rows (each is billed). Default 100. |
maxCompanies | integer | Safety cap on boards scanned. Default 50. |
includeDescription | boolean | Add the plain-text description. Default false. |
proxyConfiguration | object | Apify datacenter proxy (default on). |
At least one of companies or useBuiltInSeedList is required; otherwise the run fails with a clear message.
Output
Real rows from a production run (Coinbase board):
{"jobId": "greenhouse:coinbase:8093264","ats": "greenhouse","companySlug": "coinbase","companyName": "Coinbase","title": "Accounting Manager, GL Operations & Intercompany","titleFamily": "finance","seniority": "manager","department": "Finance","employmentType": null,"location": "Remote - USA","country": "US","isRemote": true,"salaryMin": 166345,"salaryMax": 195700,"salaryCurrency": "USD","salaryPeriod": "YEAR","annualSalaryMin": 166345,"annualSalaryMax": 195700,"annualSalaryMid": 181022.5,"rangeWidthPct": 17.6,"salaryLabel": "Annual base salary range (excluding equity and bonus)","salaryRangesCount": 1,"salaryRanges": [{"min": 166345, "max": 195700, "currency": "USD", "period": "YEAR", "label": "Annual base salary range (excluding equity and bonus)"}],"salarySource": "greenhouse.pay_input_ranges","salaryPeriodSource": "label","jobUrl": "https://www.coinbase.com/careers/positions/8093264?gh_jid=8093264","applyUrl": null,"publishedAt": "2026-07-29T00:03:36.000Z","updatedAt": "2026-09-28T17:18:44.000Z","description": null,"scrapedAt": "2026-10-05T15:37:30.737Z"}
An hourly posting looks like salaryMin: 40, salaryMax: 40, salaryPeriod: "HOUR", annualSalaryMid: 83200. Some boards publish a single value, so min can equal max (rangeWidthPct: 0).
Output fields & fill rates
Fill rates are measured on production runs and depend on the boards you scan. The first table comes from the medium run KGv42gkaxhtTFQtjc (40 rows). That run returned Greenhouse rows only (companyName is filled on every row), so it describes Greenhouse.
| Field | Fill rate (Greenhouse rows, 40/40 unless stated) |
|---|---|
jobId, ats, companySlug, companyName, title, titleFamily, jobUrl | 100% |
salaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryLabel, salaryRanges, salaryRangesCount, salarySource, salaryPeriodSource | 100% |
annualSalaryMin, annualSalaryMax, annualSalaryMid, rangeWidthPct | 100% |
department, location, country, isRemote, publishedAt, updatedAt, scrapedAt | 100% |
seniority | 87.5% (inferred from the title; null when the title has no seniority word) |
employmentType, applyUrl | 0%: Greenhouse's public board API does not provide them |
description | 0% unless includeDescription is enabled |
Mixed proof run K7KmU5rLiHj9hLAyK (input lever:outreach + ashby:ramp, 20 rows, first row from Ashby ramp, salarySource: "ashby.compensationTiers"). Its rows are most likely Ashby only, because the 20-row cap is reached on the first board, so it is treated as an Ashby proof:
| Field | Fill rate (20 rows) |
|---|---|
employmentType, applyUrl | 100% |
companyName, updatedAt | 0% (not provided for these vendors) |
salaryLabel | 35% |
seniority | 40% |
description | 0% unless includeDescription is enabled |
| all other fields in the table above | 100% |
The per-row vendor split of that run is not recorded in the report, so it does not prove Lever. Lever is proven by a dedicated Lever-only run (INPUT.lever-only.json: lever:outreach + lever:zoox, atsSources: ["lever"], 10 rows), listed in TEST_REPORT.json under production.proof_runs; the extractor is also covered by unit tests on a real Lever fixture.
What differs by vendor (from the extractor code, covered by unit tests, and consistent with the runs above):
| Field | Greenhouse | Lever | Ashby |
|---|---|---|---|
companyName, updatedAt | filled | always null (use companySlug) | always null (use companySlug) |
employmentType, applyUrl | always null | filled when the board sets them | filled when the board sets them |
salaryLabel | filled (pay-range title) | always null | filled when the tier has a title |
salaryPeriod source | inferred from the range label (salaryPeriodSource: "label") | structured | structured |
How to use via API
curl
curl -X POST "https://api.apify.com/v2/acts/~pay-transparency-salary-jobs-feed/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"companies": ["greenhouse:coinbase", "lever:outreach", "ashby:ramp"], "remoteOnly": true, "maxResults": 50}'
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('YOUR_USERNAME/pay-transparency-salary-jobs-feed').call({companies: ['greenhouse:coinbase', 'ashby:ramp'],countries: ['US'],minAnnualSalary: 150000,maxResults: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.length, items[0]);
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("YOUR_USERNAME/pay-transparency-salary-jobs-feed").call(run_input={"companies": ["greenhouse:coinbase", "lever:outreach"],"remoteOnly": True,"includeDescription": False,"maxResults": 50,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(len(items), items[0])
Pricing
Pay per result: one event per salary row delivered. Price per 1,000 results depends on your Apify plan:
| Plan | Per 1,000 results |
|---|---|
| Free | $0.54 |
| Bronze | $0.47 |
| Silver | $0.41 |
| Gold and above | $0.36 |
Platform usage (compute, proxy) is billed separately by Apify; in the measured medium run it was about $0.0004 for 40 rows (roughly $0.01 per 1,000 results). Set maxResults or the run's maximum charge to cap spend.
Troubleshooting
- "Invalid input: Provide companies or enable useBuiltInSeedList": add at least one board or turn on the built-in list.
- Few or no rows: not every company publishes pay ranges, and only matching postings are returned. Loosen filters (countries, keywords,
minAnnualSalary) or add more boards. - A board is skipped: check the log; the slug may be wrong or the board not public. Use
ats:slugor the public board URL. countryis null: the location text could not be mapped to a country; uselocation.- Currencies differ: no FX conversion is done; filter with
currenciesor convert downstream.
FAQ
Which sources are supported? Public Greenhouse, Lever and Ashby job boards. Other job sites are not covered.
Does it log in or use private data? No. It reads publicly available board data only.
Is the salary the total compensation? It is whatever the employer discloses; see salaryLabel (often "base salary excluding equity and bonus").
Can I schedule it? Yes, use Apify schedules and compare runs via jobId and updatedAt.
Is it legal? The data is published by employers, often because of pay-transparency rules. You remain responsible for your use and for complying with applicable laws and the sites' terms.
Keywords
job salary data scraper, salary range scraper, pay transparency jobs, jobs with salary, Greenhouse jobs scraper, Lever jobs scraper, Ashby jobs scraper, salary benchmarking data, compensation data, remote jobs salary, job postings API, ATS jobs feed
Hashtags
#salarydata #paytransparency #jobsdata #greenhouse #lever #ashby #compensation #recruiting #hrtech #remotejobs