# Salary Data API: Pay Benchmarks From Live Job Postings (`atsfeed/job-salary-benchmarks`) Actor

Pay ranges for any job title and location, from the salaries stated in open job postings. Median, percentiles, seniority and country breakdowns, with sample postings.

- **URL**: https://apify.com/atsfeed/job-salary-benchmarks.md
- **Developed by:** [Velavalapalli Mohana Durga Sai Ram](https://apify.com/atsfeed) (community)
- **Categories:** Jobs, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $13.00 / 1,000 salary benchmarks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Salary Benchmarks do?

Get pay ranges for any job title and location, built from the salaries employers state in their own open job postings. Each benchmark gives the **median, percentiles, average range and a breakdown by seniority and country**, with sample postings as evidence. The index holds about **170,000 open job postings that state pay** and is refreshed daily.

Use it as a **salary data API**: send job titles and places, and get back one clean benchmark per title and location, ready for a spreadsheet, a compensation tool or an AI agent.

### Why use Salary Benchmarks?

- **Current pay, not old surveys.** Benchmarks come from jobs that are open now, not from salaries people reported years ago.
- **Employers' own numbers.** Pay transparency laws in several US states, and similar rules spreading in Europe, mean more employers publish a range in the posting itself.
- **Evidence you can check.** Every benchmark links recent postings with their stated pay.
- **Many benchmarks in one run.** Ten titles across ten cities is one run with 100 rows.
- **You only pay for useful rows.** Benchmarks with too few postings are skipped and not charged.

#### Who uses salary benchmarks?

- **HR and compensation teams** setting salary bands and offers for a role in a city or country.
- **Recruiters and agencies** pricing searches and briefing hiring managers with market data.
- **Job seekers and career sites** showing what a role pays where.
- **Salary tools and AI agents** that need clean numbers through an API.

### What data can Salary Benchmarks extract?

| Field | Type | Description |
|---|---|---|
| `jobTitle`, `location` | text | The title and place you asked for |
| `median` | number | Median yearly pay, in the main currency |
| `p10`, `p25`, `p75`, `p90` | number | Percentiles of yearly pay |
| `averageRangeLow`, `averageRangeHigh` | number | Average bottom and top of the stated ranges |
| `currency`, `period` | text | Currency of the benchmark; the period is always `year` |
| `postingsWithPay`, `companies` | number | How many postings and companies the benchmark uses |
| `confidence` | text | `high` from 30 postings, `medium` from 10, `low` below |
| `bySeniority`, `byCountry` | list | Median pay per level and per country |
| `otherCurrencies` | list | Postings in other currencies, summarized separately |
| `sampleJobs` | list | Recent postings with their pay and a link |
| `summary` | text | One sentence, such as "$185,000 median yearly pay from 1105 job postings at 591 companies." |

### How to get salary data for a job title

1. Enter one or more **job titles**, such as `data engineer` or `"account executive"`.
2. Add **locations** if you want one benchmark per place: a city, state, country or two-letter country code.
3. Click **Start**. You get one benchmark for every title and location pair.
4. Download the results, or read them through the API.

#### Example input

```json
{
  "jobTitles": ["data engineer", "product manager"],
  "locations": ["United States", "London", "Germany"],
  "minPostings": 5
}
```

### How much does salary data cost?

You pay per benchmark returned, and higher Apify plans pay less per benchmark. The pricing panel on this page shows the price for your plan. On the Free and Starter plans:

| Benchmarks returned | Cost |
|---|---|
| 10 | $0.20 |
| 100 | $2.00 |
| 1,000 | $20.00 |

Benchmarks with too few postings are skipped and not charged. Platform usage is included.

### Input

See the **Input** tab for every option:

| Option | What it does |
|---|---|
| Job titles | One benchmark per title. Words in any order, or use double quotes for an exact phrase |
| Locations | One benchmark per location for each title. Leave empty for all locations |
| Exclude title keywords | Skip titles containing these, such as "intern" |
| Seniority | Only count postings at these levels |
| Only remote jobs | Only count remote postings |
| Count remote jobs that name no country | Off by default, because pay for worldwide remote jobs is often set for another market |
| Posted within the last N days | 0 uses every open posting in the index |
| Minimum postings per benchmark | Benchmarks with fewer postings that state pay are skipped and not charged |
| Sample jobs per benchmark | Recent postings with their pay and a link |

### Output

Download the dataset as JSON, CSV, Excel, XML, RSS or HTML. Each benchmark looks like this:

#### Example output

```json
{
  "jobTitle": "data engineer",
  "location": "London",
  "summary": "£95,000 median yearly pay from 17 job postings at 12 companies.",
  "currency": "GBP",
  "period": "year",
  "median": 95000,
  "p10": 64000,
  "p25": 82000,
  "p75": 110000,
  "p90": 120000,
  "averageRangeLow": 85000,
  "averageRangeHigh": 105000,
  "postingsWithPay": 17,
  "companies": 12,
  "confidence": "medium",
  "bySeniority": [{ "seniority": "mid", "postings": 9, "median": 85000 }, { "seniority": "senior", "postings": 8, "median": 105000 }],
  "byCountry": [{ "country": "GB", "postings": 17, "median": 95000 }],
  "otherCurrencies": [],
  "sampleJobs": [{ "title": "Senior Data Engineer", "company": "Acme", "location": "London, UK", "salary": { "min": 95000, "max": 115000, "currency": "GBP", "period": "year" }, "postedDate": "2026-11-03", "url": "https://job-boards.greenhouse.io/acme/jobs/123" }],
  "dataAsOf": "2026-11-05T22:01:18.962Z"
}
```

### How the numbers are worked out

- Each posting counts once, at the midpoint of its stated range. A posting that states one figure counts at that figure.
- Hourly pay is converted to yearly at 2,080 hours, and monthly pay at 12 months. Pay for other periods is left out.
- Each benchmark uses the currency most of its postings state. Postings in other currencies are summarized in `otherCurrencies` and not converted.
- Bonus, equity and benefits are not included, because postings rarely state them in a comparable way.

### Tips for better benchmarks

- Use a country instead of a city when a benchmark comes back with `low` confidence.
- Put a title in double quotes for an exact phrase, such as `"product manager"`.
- Raise **Minimum postings per benchmark** to 10 or more when you only want solid numbers.

### Use Salary Benchmarks with the API and AI agents

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('atsfeed/job-salary-benchmarks').call({
  jobTitles: ['data engineer'],
  locations: ['United States', 'London'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

AI agents in Claude, ChatGPT, Cursor or any MCP client can call this Actor as a tool through the Apify MCP server at `mcp.apify.com`. The **API** tab has Python, cURL and more.

### FAQ

#### Where does the salary data come from?

From the pay that employers state in their open job postings on Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio and Breezy job boards. No personal data is used: benchmarks describe what employers advertise, not what any person is paid.

#### Why is a benchmark missing?

It had fewer postings that state pay than your **Minimum postings per benchmark**. It was skipped and not charged. Try a broader title or a country instead of a city.

#### Why are some benchmarks in US dollars outside the US?

Some international postings state pay in US dollars. The Actor uses the currency most postings state and lists the rest in `otherCurrencies`.

### Coverage and accuracy

- **Index size, November 2026:** about 170,000 open job postings that state pay. **By currency:** US dollars 150,000, euros 8,600, British pounds 6,000, Indian rupees 2,800, Canadian dollars 1,900.
- Coverage is strongest in the United States, where more employers state pay.
- A city matches postings that name that city. A country also matches postings that list it among several countries.
- Pay is taken from the employer's posting with fixed rules. Ranges can be wide, and a few postings state pay for a different market than their location. Check the sample jobs before relying on a number.

### Related Actors

- [Career Site Jobs API](https://apify.com/atsfeed/ats-job-search): open jobs from company career sites on eight applicant tracking systems, in one search.
- [Daily Jobs Feed](https://apify.com/atsfeed/daily-jobs-feed): every new job from company career sites in one scheduled run.
- [Remote Jobs Scraper](https://apify.com/atsfeed/remote-jobs-search): remote jobs straight from company career sites.
- [Hiring Signals & Technographics](https://apify.com/atsfeed/hiring-signals-technographics): companies hiring for a role or naming a tool in their postings.
- Job search for a single source: [Greenhouse](https://apify.com/atsfeed/greenhouse-jobs-search), [Lever](https://apify.com/atsfeed/lever-jobs-search), [Ashby](https://apify.com/atsfeed/ashby-jobs-search), [Workable](https://apify.com/atsfeed/workable-jobs-search), [SmartRecruiters](https://apify.com/atsfeed/smartrecruiters-jobs-search).

### Questions

Found a wrong number, or want a market covered better? Open an issue on the **Issues** tab with an example.

# Actor input Schema

## `jobTitles` (type: `array`):

One benchmark per title, for each location below. Words in a title can be in any order: "data engineer" also matches "Engineer, Data". Put a title in double quotes for an exact phrase.

## `locations` (type: `array`):

One benchmark per location for each title. Any city, state, country or two-letter country code, in plain words. Leave empty for one benchmark per title across all locations.

## `excludeTitleKeywords` (type: `array`):

Skip postings whose title contains any of these, for example "intern" or "contract".

## `seniority` (type: `array`):

Only count postings at these levels, detected from the job title. Every benchmark also includes a breakdown by seniority.

## `remoteOnly` (type: `boolean`):

Only count postings marked remote.

## `includeGlobalRemote` (type: `boolean`):

Applies when you set locations. Off by default, because pay for worldwide remote jobs is often set for another market.

## `postedWithinDays` (type: `integer`):

0 uses every open posting in the index. A shorter window gives fresher but smaller samples.

## `minPostings` (type: `integer`):

Benchmarks with fewer postings that state pay are skipped and not charged.

## `sampleJobs` (type: `integer`):

Recent postings with their stated pay and a link, as evidence.

## Actor input object example

```json
{
  "jobTitles": [
    "data engineer",
    "product manager"
  ],
  "locations": [
    "United States",
    "London"
  ],
  "remoteOnly": false,
  "includeGlobalRemote": false,
  "postedWithinDays": 0,
  "minPostings": 3,
  "sampleJobs": 3
}
```

# Actor output Schema

## `results` (type: `string`):

Median, percentiles and breakdowns for each job title and location.

## `summary` (type: `string`):

Postings counted, benchmarks returned and benchmarks skipped for too few postings.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "jobTitles": [
        "data engineer",
        "product manager"
    ],
    "locations": [
        "United States",
        "London"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("atsfeed/job-salary-benchmarks").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "jobTitles": [
        "data engineer",
        "product manager",
    ],
    "locations": [
        "United States",
        "London",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("atsfeed/job-salary-benchmarks").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "jobTitles": [
    "data engineer",
    "product manager"
  ],
  "locations": [
    "United States",
    "London"
  ]
}' |
apify call atsfeed/job-salary-benchmarks --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atsfeed/job-salary-benchmarks"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/uaX2vvhdFtAh2eTQJ/builds/52b4pqMijOrYGDxQH/openapi.json
