# Ashby Jobs Scraper - With Salary Ranges (`make_no_mistakes/ashby-jobs-scraper`) Actor

Scrape open jobs with salary ranges from any company on Ashby (jobs.ashbyhq.com). Type a company name or domain. Structured min/max salary, currency, interval, equity flag, workplace type, department and team. Delta mode for daily runs.

- **URL**: https://apify.com/make_no_mistakes/ashby-jobs-scraper.md
- **Developed by:** [Make No Mistakes LLC](https://apify.com/make_no_mistakes) (community)
- **Categories:** Jobs, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 job scrapeds

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

## Ashby Jobs Scraper: With Salary Ranges

Scrape every open job, **with its salary range**, from any company's Ashby job board
(`jobs.ashbyhq.com`). Type a company name, a domain or a board URL. Each job comes back with
structured min and max pay, currency, pay interval, an annualized range, an equity flag, Ashby's
own compensation summary, department, team, workplace type, locations and the apply URL.

| Company | Title | Salary | Equity | Department | Workplace / location | Apply |
|---|---|---|---|---|---|---|
| OpenAI | Research Engineer | 250,000 - 445,000 USD / year | yes | Research | San Francisco | [apply](https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b/application) |
| OpenAI | Researcher, Robustness & Safety Training | 380,000 - 500,000 USD / year | yes | Safety Systems | San Francisco, London | [apply](https://jobs.ashbyhq.com/openai/2560ed50-5535-42b8-b069-9ebc28ce7493/application) |
| Ramp | Security Engineer, Cloud | 211,400 - 290,600 USD / year | yes | Engineering | Hybrid, New York (HQ) | [apply](https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application) |
| Ramp | Mobile Engineer, Android | 189,000 - 330,000 USD / year | yes | Engineering | Hybrid, New York (HQ) | [apply](https://jobs.ashbyhq.com/ramp/f564dcf9-9390-4a3f-896f-8047a5086040/application) |
| Perplexity | Product Marketing Manager, Partnerships | 190,000 - 250,000 USD / year | yes | Marketing & Communications | Hybrid, San Francisco | [apply](https://jobs.ashbyhq.com/perplexity/d5bc2302-202f-4596-9c4d-8720d1e79064/application) |

*Real rows from the default run on 2026-10-03.*

**Try it: the default input returns 300 jobs (100 each from OpenAI, Ramp and Perplexity) for about
$0.60, and 271 of those 300 carry a salary range.** It finishes in about 5 seconds. No login, no
proxy, no API key: it reads Ashby's official public Job Postings API.

### Why Ashby, and why this Actor

Ashby is the ATS of choice for a large share of venture-backed startups (OpenAI, Ramp, Plaid,
Harvey, Snowflake, Cohere, Replit, Benchling and many more), and its public API publishes the
richest compensation data of any job board: a structured block with salary, equity, bonus and
commission components, each with min, max, currency and interval.

How much salary data is there? On 20 well-known Ashby boards on 2026-10-03, **1,825 of 2,832 open
jobs (64%) had a structured salary range; on the 13 boards that publish pay at all, 78% did**
(Ramp 96%, Plaid 97%, Modal 92%, OpenAI 81%). Some employers (Notion, Linear, Cursor) publish none,
and `onlyWithSalary` filters those out.

This Actor puts that data first:

- **Salary columns lead every item**: `salary_min`, `salary_max`, `salary_currency`,
  `salary_period`, then `salary_summary` (Ashby's own "$235K - $385K, Offers Equity" string).
- **Annualized pay** in `salary_min_annual` / `salary_max_annual` (hour x 2080, week x 52, month x
  12\), so hourly intern rates and annual salaries sort and filter on one scale.
- **`offers_equity`** and **`compensation_components`**: every component Ashby publishes (Salary,
  EquityPercentage, EquityCashValue, Bonus, Commission), not only the base.
- **`minSalary`** filter on the annualized top of the range, and **`workplaceTypes`** (Remote,
  Hybrid, OnSite) from Ashby's own field.
- **Company name in, board slug out.** `ramp.com` resolves to `ramp`; a company that is not on Ashby
  gets a free `company_not_found` row naming the ATS it does use.

### Use cases

- **Salary benchmarking and comp research:** pay bands by title, team, level and city across the
  startups you compete with for talent.
- **Recruiting:** track which teams your competitors are hiring for, and at what pay.
- **Job seekers and job boards:** salary-first listings ("$200K+ remote engineering jobs at
  AI startups") with `minSalary`, `workplaceTypes` and `keywords`.
- **Investors and analysts:** hiring velocity by department as a growth signal for private companies.

### Input

```json
{
  "companies": ["OpenAI", "ramp.com", "https://jobs.ashbyhq.com/plaid", "Harvey"],
  "keywords": ["engineer"],
  "locations": ["San Francisco", "New York", "Remote"],
  "remoteOnly": false,
  "postedWithinDays": 30,
  "onlyWithSalary": true,
  "minSalary": 180000,
  "workplaceTypes": ["Remote", "Hybrid"],
  "onlyNewSinceLastRun": false,
  "includeDescription": true,
  "maxItems": 1000,
  "maxItemsPerCompany": 100
}
```

| Field | What it does |
|---|---|
| `companies` | Names, domains, board slugs or board URLs, mixed freely. |
| `keywords` | Keep jobs whose title, department or team contains any of these words. |
| `locations` | Keep jobs whose location contains any of these strings. |
| `remoteOnly` | Keep only jobs flagged remote by Ashby or whose location says remote. |
| `postedWithinDays` | Keep only jobs published in the last N days. |
| `onlyWithSalary` | Ashby-only: keep only jobs with a structured salary range. |
| `minSalary` | Ashby-only: keep jobs whose annualized salary_max is at least this (in the posting's currency). |
| `workplaceTypes` | Ashby-only: Remote, Hybrid, OnSite. |
| `onlyNewSinceLastRun` | Delta mode: only jobs you have not received before (see below). |
| `deltaStateName` | Name of the key-value store that remembers delivered jobs, one per schedule. |
| `includeDescription` | Set false to drop the description fields (smaller items, same price). |
| `maxItems` | Total jobs per run, and so your spend cap. |
| `maxItemsPerCompany` | Jobs per company (default 100). Set 0 for whole boards. |

### Output

Every job uses the same normalized schema as the
[Multi-ATS Job Board API](https://apify.com/make_no_mistakes/multi-ats-job-board-api), with the
salary fields first and Ashby-specific fields added:

```json
{
  "record_type": "job",
  "company": "OpenAI",
  "title": "Data Engineer",
  "salary_min": 235000,
  "salary_max": 385000,
  "salary_currency": "USD",
  "salary_period": "YEAR",
  "salary_summary": "$235K – $385K • Offers Equity",
  "salary_min_annual": 235000,
  "salary_max_annual": 385000,
  "offers_equity": true,
  "department": "Applied AI",
  "team": "Applied AI Engineering",
  "workplace_type": "Hybrid",
  "location_raw": "San Francisco | Mountain View",
  "city": "San Francisco",
  "state": "California",
  "country": "US",
  "employment_type": "FULL_TIME",
  "posted_at": "2023-09-26",
  "apply_url": "https://jobs.ashbyhq.com/openai/fc5bbc77-a30c-4e7a-9acc-8a2e748545b4/application",
  "company_slug": "openai",
  "ats": "ashby",
  "job_id": "fc5bbc77-a30c-4e7a-9acc-8a2e748545b4",
  "compensation_components": [
    {"type": "EquityCashValue", "min": null, "max": null, "currency": "USD", "interval": "YEAR"},
    {"type": "Salary", "min": 235000, "max": 385000, "currency": "USD", "interval": "YEAR"}
  ],
  "secondary_locations": ["Mountain View"],
  "job_url": "https://jobs.ashbyhq.com/openai/fc5bbc77-a30c-4e7a-9acc-8a2e748545b4"
}
```

`description_html` and `description_text` (Ashby's own plain-text version) carry the full posting,
and `raw` keeps the untouched Ashby record. Ashby's posting API has no "updated" timestamp, so
`updated_at` is null by design.

Dataset views: **Jobs** (salary columns first), **Ashby details** and **Companies not on Ashby**.
`RUN_SUMMARY` in the key-value store records how each company was resolved and the jobs per company.

### Delta mode for scheduled runs

Set `onlyNewSinceLastRun: true` and schedule the Actor. The first run returns everything and
remembers it; later runs return only jobs not delivered before, and **never charge twice for the
same job**. State lives in a named key-value store in your own account (`deltaStateName`), one
record per board.

### Pricing

Pay per event, no subscription:

| | Free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Per job | $0.002 | $0.0015 | $0.001 | $0.0006 |
| Per run start | $0.001 | $0.001 | $0.001 | $0.001 |

- 100 jobs on the Free plan: about **$0.20**. 1,000 jobs: about **$2.00**.
- Filters run before charging: with `onlyWithSalary` you pay only for jobs that have a salary.
- `company_not_found` rows are free.
- `maxItems` is a hard spend cap. If your run's **Maximum cost per run** is too low for the jobs in
  scope, the run says so on its status line and in `RUN_SUMMARY`.

### No login, no proxy, official public API

Ashby publishes its Job Postings API (`api.ashbyhq.com/posting-api/job-board/{org}`) so that
employers' jobs can be listed anywhere. No account, cookies or proxies are involved.

### Related Actors

- [Multi-ATS Job Board API](https://apify.com/make_no_mistakes/multi-ats-job-board-api): one run
  across nine ATS platforms, for company lists that span Ashby, Greenhouse, Lever, Workday and more.
- [Company ATS Detector](https://apify.com/make_no_mistakes/company-ats-detector) (free): which
  ATS does a company use?
- [Greenhouse Jobs Scraper](https://apify.com/make_no_mistakes/greenhouse-jobs-scraper) (pay
  ranges too), [Workday Jobs Scraper](https://apify.com/make_no_mistakes/workday-jobs-scraper) and
  [Lever Jobs Scraper](https://apify.com/make_no_mistakes/lever-jobs-scraper).

### API example

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/make_no_mistakes~ashby-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["OpenAI", "Ramp"], "minSalary": 200000, "workplaceTypes": ["Remote"]}'
```

### FAQ

**Why is salary missing on some jobs?** The employer did not publish one on Ashby. Use
`onlyWithSalary` to drop those (you are not charged for filtered-out jobs).

**Is the salary base pay or total compensation?** `salary_min`/`salary_max` are the Salary
component (base). Equity, bonus and commission are listed separately in `compensation_components`.

**Is this affiliated with Ashby?** No. This is an independent tool, not affiliated with, endorsed by
or sponsored by Ashby, Inc. The name only describes which job boards it reads.

Published by Make No Mistakes LLC. Questions and feature requests: open an issue on this Actor's
Issues tab.

# Actor input Schema

## `companies` (type: `array`):

Companies whose Ashby job boards you want. Accepts company names ("OpenAI"), domains ("ramp.com"), board slugs ("notion") or board URLs ("https://jobs.ashbyhq.com/ramp"), mixed freely. A company that is not on Ashby comes back as a free company_not_found row naming the ATS it does use. Default: \["OpenAI", "Ramp", "Perplexity"].

## `keywords` (type: `array`):

Keep a job when its title, department or team contains any of these words (case-insensitive). Default: empty = every job. Example: \["engineer", "data"].

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

Keep a job when any of these strings appears in its location, city, state or country (case-insensitive). Default: empty = every location. Example: \["New York", "London", "US"].

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

Default: false. When true, keep only jobs flagged remote or whose location says remote, anywhere or distributed.

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

Keep only jobs posted (or updated) in the last N days. Default: empty = the whole board. Example: 7.

## `onlyWithSalary` (type: `boolean`):

Default: false. When true, keep only jobs with a structured salary range.

## `minSalary` (type: `integer`):

Keep only jobs whose annualized salary_max is at least this amount, in the posting's own currency (hourly, weekly and monthly ranges are annualized). Jobs without a salary are dropped when this is set. Default: empty. Example: 150000.

## `workplaceTypes` (type: `array`):

Keep only jobs with this Ashby workplace type. Default: empty = any.

## `onlyNewSinceLastRun` (type: `boolean`):

Default: false. When true, return only jobs this setup has not returned before, so a scheduled run never pays twice for the same posting. State is kept per board in a named key-value store in your own account (see deltaStateName). The first run returns everything and records it. Already-delivered jobs are dropped before they are written and are never charged.

## `deltaStateName` (type: `string`):

Name of the key-value store in your account that remembers delivered jobs. Only used with onlyNewSinceLastRun. Use a different name per independent schedule. Default: "ashby-jobs-scraper-delta".

## `includeDescription` (type: `boolean`):

Default: true. Set false to drop description_html and description_text, making each item about 10x smaller. The price is the same either way.

## `maxItems` (type: `integer`):

Maximum jobs returned across all companies, filled in company order. This is also your spend cap: $0.002 per job, so 1,000 jobs = $2.00. Default: 1000. 0 = unlimited.

## `maxItemsPerCompany` (type: `integer`):

Maximum jobs returned per company, so one huge board cannot use up the run. Default: 100. 0 = no per-company cap (a large employer can have several thousand open jobs).

## Actor input object example

```json
{
  "companies": [
    "OpenAI",
    "Ramp",
    "Perplexity"
  ],
  "remoteOnly": false,
  "onlyWithSalary": false,
  "onlyNewSinceLastRun": false,
  "includeDescription": true,
  "maxItems": 1000,
  "maxItemsPerCompany": 100
}
```

# Actor output Schema

## `jobs` (type: `string`):

One item per open Ashby job (record_type = job), plus one free item per input that is not on Ashby (record_type = company_not_found).

## `jobsCsv` (type: `string`):

The same items as CSV.

## `runSummary` (type: `string`):

RUN_SUMMARY record: filters used, jobs per company, how each company was resolved, companies not on this platform, delta-mode counts, and whether the run was truncated by a cost limit.

# 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 = {
    "companies": [
        "OpenAI",
        "Ramp",
        "Perplexity"
    ],
    "maxItems": 1000,
    "maxItemsPerCompany": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("make_no_mistakes/ashby-jobs-scraper").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 = {
    "companies": [
        "OpenAI",
        "Ramp",
        "Perplexity",
    ],
    "maxItems": 1000,
    "maxItemsPerCompany": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("make_no_mistakes/ashby-jobs-scraper").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 '{
  "companies": [
    "OpenAI",
    "Ramp",
    "Perplexity"
  ],
  "maxItems": 1000,
  "maxItemsPerCompany": 100
}' |
apify call make_no_mistakes/ashby-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,make_no_mistakes/ashby-jobs-scraper"
        }
    }
}
```

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/6AsFKNxwHmJpyfvox/builds/toDENwm1Cx8pv0Ec1/openapi.json
