# Ashby Jobs Scraper & API: Any Board or All Ashby Jobs (`deriverge/ashby-jobs-scraper`) Actor

Scrape any Ashby job board by company, or search all 50,000+ open Ashby jobs by keyword, country, skills, seniority, remote and salary. Salary ranges, workplace type, skills, apply link, full description. New jobs only mode. JSON, CSV, API.

- **URL**: https://apify.com/deriverge/ashby-jobs-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 job listings

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

Scrape every open job from any Ashby job board: title, company, department, locations, remote flag, posting date and apply link, read live from the company's own board each time you run it. Paste board names, board links or company domains, or leave the list empty to search all 60,000+ open Ashby jobs in our daily index by keyword, country, skills, seniority, remote and salary.

You pay only for jobs returned, from $0.50 per 1,000, with no start fee. The $5 of monthly credit in Apify's Free plan covers about 5,000 jobs, so you can test it on real boards for free.

### Why use Ashby Jobs Scraper?

- **Live data, not a cached index.** Each run reads the company's Ashby job board directly. A job published this morning is in this morning's dataset, and a closed job is gone.
- **Company domains work.** Enter a domain and the actor finds the Ashby job board, confirms it belongs to that company and only then scrapes it. A wrong company's jobs are worse than none.
- **New jobs only, on a schedule.** Turn on `newOnly`, schedule the task daily, and each run returns just the jobs that appeared since the previous one.
- **Or search every Ashby job.** Leave Career sites empty and the actor searches all 60,000+ open Ashby jobs in our daily index of company career sites, with the same filters and fields.
- **Low, predictable price.** You pay per job returned. Filtered jobs, jobs you already received and companies on another system cost nothing.
- **No browser, no proxies, no login.** The actor calls the same public Ashby interface the careers page uses, so a run over a few boards finishes in seconds.

### What data does Ashby Jobs Scraper extract?

| Field | What it contains |
|---|---|
| `title` | Job title |
| `companyName` | Company name |
| `department` | Department |
| `team` | Team |
| `employmentType` | Full time, part time, contract or internship |
| `workplaceType` | On-site, hybrid or remote |
| `locations` | Primary and secondary locations |
| `remote` | `true` when the job is remote |
| `postedAt` | When the job was published |
| `salaryText` | Compensation summary, when the company publishes it |
| `seniority` | `intern`, `entry`, `mid`, `senior`, `lead`, `director` or `executive`, read from the job title (`mid` when the title names no level) |
| `jobCategory` | Job category such as `software`, `data`, `sales`, `healthcare`, `logistics` or `retail`, from the title and department |
| `countries` | Two-letter country codes read from the locations, for example `US` for "Austin, TX" |
| `workArrangement` | `remote`, `hybrid` or `onsite`, from the workplace field, the location and clear sentences in the description |
| `employmentTypes` | Normalised types: `full-time`, `part-time`, `contract`, `temporary`, `internship`, `apprenticeship`, `volunteer` |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Pay as numbers, from the salary field or a pay range written in the description |
| `salaryYearlyMin`, `salaryYearlyMax` | The same pay converted to a year, for comparing hourly and yearly jobs |
| `visaSponsorship` | `true` or `false` when the description says whether the company sponsors visas, otherwise `null` |
| `skills` | Tools, languages, platforms and certifications the job mentions, for example `Python`, `AWS`, `Salesforce`, `Excel` or `CPA` |
| `experienceYearsMin`, `experienceYearsMax` | Years of experience the description asks for: `5` for "5+ years", `3` and `5` for "3-5 years" |
| `educationLevel` | Lowest degree the description mentions: `high-school`, `associate`, `bachelor`, `master` or `doctorate` |
| `language` | Language of the job ad as a two-letter code, from the ATS or detected from the description |
| `companyWebsite` | The company website, where the ATS publishes it (Ashby, Lever, iCIMS) |
| `url`, `applyUrl` | Job page and application link |
| `description` | Full job description as plain text, with **Include the full job description** |
| `jobId`, `key` | Ashby job ID and a stable key for deduplication across runs |
| `company`, `input`, `reference` | The board name, your original input, and your own label if you passed one |

A field the company did not publish is `null`. Seniority, countries, work arrangement, employment types, salary numbers, visa sponsorship, skills, years of experience, education level and language are read by fixed rules from what the job says, not guessed.

### Who uses Ashby Jobs Scraper?

- **Recruiting and sourcing:** watch the boards of the companies you place candidates with and act the day a role opens.
- **Sales prospecting:** hiring is a buying signal. A company opening five data engineering roles is likely shopping for data tools.
- **Job boards and aggregators:** fill a niche board with fresh, first-party listings instead of reposts.
- **Market and salary research:** see which teams companies are growing, where, and at what pay where it is published.

### How much does it cost to scrape Ashby jobs?

You pay per job returned. There is no start fee and no charge for compute time or proxies.

| | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 1,000 jobs | $1.00 | $0.80 | $0.65 | $0.50 |

For example, 10,000 jobs cost $10.00 on the Free plan and $5.00 on the Business plan. The $5 of monthly credit in Apify's Free plan covers about 5,000 jobs, so you can try it on real boards without paying anything.

Jobs removed by your filters, jobs already returned in new-only mode and companies that are not on the system you asked for are never charged. A run that returns nothing costs nothing.

### How to scrape Ashby jobs

1. Click **Try for free** (or **Start** if you are signed in) to open the actor in Apify Console.
2. In **Career sites**, add one company per line: a board name such as `notion`, a link such as `https://jobs.ashbyhq.com/notion` or a company domain such as `linear.app`.
3. Optionally narrow the results with **Title keywords**, **Exclude title keywords**, **Locations**, **Remote jobs only** or **Posted within the last N days**.
4. Click **Start**. Rows appear in the **Output** tab within seconds.
5. Download the dataset as JSON, CSV, Excel or HTML, or read it through the API.

### Input example

```json
{
  "companies": [
    "notion",
    "https://jobs.ashbyhq.com/linear"
  ],
  "remoteOnly": false,
  "maxJobsPerCompany": 50
}
```

### Output example

A real row from a run on September 26, 2026:

```json
{
  "key": "ashby:linear:d3bc1ced-3ce4-4086-a050-555055dbb1ff",
  "ats": "ashby",
  "company": "linear",
  "companyName": "Linear",
  "jobId": "d3bc1ced-3ce4-4086-a050-555055dbb1ff",
  "title": "Senior / Staff Fullstack Engineer",
  "locations": [
    "Europe"
  ],
  "remote": true,
  "department": "Product",
  "team": "Engineering",
  "employmentType": "FullTime",
  "workplaceType": "Remote",
  "salaryText": null,
  "postedAt": "2021-04-27T20:13:45.158Z",
  "updatedAt": null,
  "url": "https://jobs.ashbyhq.com/linear/d3bc1ced-3ce4-4086-a050-555055dbb1ff",
  "applyUrl": "https://jobs.ashbyhq.com/linear/d3bc1ced-3ce4-4086-a050-555055dbb1ff/application",
  "description": null,
  "language": null,
  "reference": null,
  "input": "ashby:linear"
}
```

In the **Output** tab the **Overview** view shows the same data as a table. Every run also stores a `SUMMARY` record with the jobs found and returned per company, and how each domain was matched to its board.

### Get only new jobs every day

Turn on **Return only jobs posted since the last run** (`newOnly`), give the run a **Watch name** or save the input as a task, and schedule it daily. Each run compares the boards with the previous snapshot and returns only jobs that were not there before, so every job reaches you once and is paid once. Closed and retitled jobs are counted in the `CHANGES` record of the run.

### Tips and limitations

- Pay comes from the salary field when the company publishes one, and from a pay range written in the description, so turn on **Include the full job description** to get `salaryMin` and `salaryMax` for more jobs.
- Some companies run several boards, for example one per region or brand. Add each board as its own line.
- Internal and unlisted jobs are not on public boards, so they are not returned.
- Use **Maximum jobs per company** to keep a first run small, then remove the cap.

### Integrations and API

Connect the actor to **Make**, **Zapier**, **n8n**, **Google Sheets**, **Slack** or any webhook, or call it from your own code. With the Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("deriverge/ashby-jobs-scraper").call(run_input={"companies": ["notion", "https://jobs.ashbyhq.com/linear"]})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["companyName"], job["title"], job["locations"])
```

The **API** tab on this page has the same call for Node.js and cURL, and AI agents can run the actor through the Apify MCP server.

### Is it legal to scrape Ashby job boards?

The actor reads only job postings that companies publish openly for anyone to see, through the same public interface their careers page uses, and it collects no personal data. As with any data source, make sure your use complies with the laws and terms that apply to you.

### FAQ

#### Which companies use Ashby?

Thousands, including Notion and Linear. If you are not sure which system a company uses, give the actor its domain: it checks the careers page and tells you.

#### What if a company is not on Ashby?

It is skipped at no cost and the run summary says which system it uses. [Career Site Jobs Scraper](https://apify.com/deriverge/greenhouse-lever-workday-jobs-scraper) reads fourteen systems in one run: Greenhouse, Lever, Ashby, SmartRecruiters, Workday, Workable, Recruitee, Teamtailor, BambooHR, Personio, Rippling, Breezy HR, Oracle Recruiting Cloud and iCIMS.

#### How fresh is the data?

As fresh as the board. Nothing is cached between your run and the company's job board.

#### How many jobs can I get?

All open jobs on each board. Use **Maximum jobs per company** to cap a run.

#### Do I need proxies or an API key?

No.
**Can I search all Ashby jobs without naming companies?** Yes. Leave Career sites empty and set Keywords, Countries or the other filters: the actor searches all 60,000+ open Ashby jobs in our daily index, newest first, up to **Maximum jobs (index search)**. Descriptions are read live when you turn on the description.

### Related scrapers

- [Career Site Jobs Scraper](https://apify.com/deriverge/greenhouse-lever-workday-jobs-scraper): fourteen applicant tracking systems in one table
- [Greenhouse Jobs Scraper](https://apify.com/deriverge/greenhouse-jobs-scraper): any Greenhouse job board
- [Lever Jobs Scraper](https://apify.com/deriverge/lever-jobs-scraper): any Lever careers page
- [Workday Jobs Scraper](https://apify.com/deriverge/workday-jobs-scraper): any myworkdayjobs career site
- [Remote Jobs Scraper](https://apify.com/deriverge/remote-jobs-scraper): six remote job boards in one table

### Support and feedback

Missing a field, found a board that does not work, or need another system? Open an issue in the **Issues** tab and it will be answered, usually within a day. If the actor saves you time, a short review helps other people find it.

# Actor input Schema

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

One entry per company: the Ashby board name (notion), the Ashby URL (https://jobs.ashbyhq.com/notion), or just the company domain (ramp.com), which the actor resolves to the right board before it scrapes. Inputs pointing at another applicant tracking system are skipped and listed in the run summary. Leave this empty to search every open Ashby job in our daily index instead, by keywords, country, seniority and the other filters below.

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

Keep only jobs whose title, department or team contains at least one of these words, case-insensitive. Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Drop jobs whose title, department or team contains any of these words.

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

Keep only jobs whose location contains one of these strings, for example "London", "United States", "Remote".

## `countries` (type: `array`):

Keep only jobs in these countries: English names or two-letter codes, for example United States, Germany, UK or DE. Read from the job location, so "Austin, TX" counts as United States.

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

Keep only jobs the ATS marks as remote or whose location says remote.

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

Drop jobs older than this many days when the ATS provides a posting date. Leave empty for no limit.

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

Read from the job title in English, German, French, Spanish and more. Titles without a level count as mid.

## `categories` (type: `array`):

Read from the job title (and the department when the title says nothing), for example software, healthcare, sales or logistics. Jobs whose title fits no category are left out when this filter is on.

## `workArrangement` (type: `array`):

From the workplace field, the location and clear sentences in the description. Jobs with a place and no remote or hybrid mention count as on-site.

## `employmentTypes` (type: `array`):

Only jobs whose employment field or title states one of these types.

## `hasSalary` (type: `boolean`):

Only jobs that state pay, from the salary field or a pay range in the description (turn on the description to catch more).

## `minYearlySalary` (type: `integer`):

Only jobs whose pay, converted to a year (hourly × 2,080, monthly × 12), reaches this amount in the currency below, for example 120000.

## `salaryCurrency` (type: `string`):

Currency of the minimum yearly salary: USD, EUR, GBP, CAD, AUD and so on.

## `visaSponsorship` (type: `boolean`):

Only jobs whose description says the company sponsors visas. Reads the description.

## `descriptionKeywords` (type: `array`):

Only jobs whose title or description contains any of these, for example "python" or "SAP". Reads the description.

## `excludeDescriptionKeywords` (type: `array`):

Drop jobs whose title or description contains any of these, for example "security clearance".

## `skills` (type: `array`):

Only jobs that ask for all of these skills, for example Python, AWS or Salesforce. Known tools, languages and certifications match their other spellings (golang, k8s, postgres); anything else is matched as a whole word in the title or description.

## `maxYearsOfExperience` (type: `integer`):

Leave out jobs whose description asks for more years of experience than this, for example 2 for junior roles. Jobs that do not state years are kept.

## `languages` (type: `array`):

Only jobs written in these languages, as two-letter codes or names, for example en or English to find English-language jobs in Germany. Detected from the description.

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

Adds the job description as plain text. Costs one extra request per job on SmartRecruiters, Workable, Workday and BambooHR, so runs take longer there.

## `newOnly` (type: `boolean`):

Keeps a snapshot per watch name (or per saved task) and returns only jobs that were not in the previous snapshot. Schedule the task daily and you get a hiring-signal feed: every new opening, once, the day it appears. Closed jobs are counted in the CHANGES record.

## `watchName` (type: `string`):

Name of the snapshot used by the new-only mode, for example "competitors". Runs from a saved task get a snapshot automatically even without a name.

## `maxJobsPerCompany` (type: `integer`):

Caps the number of jobs returned per career site. Leave empty for all.

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

Cap on jobs returned when Career sites is empty and the daily index is searched, newest first; empty means 1,000.

## Actor input object example

```json
{
  "companies": [
    "notion",
    "linear"
  ],
  "remoteOnly": false,
  "hasSalary": false,
  "salaryCurrency": "USD",
  "visaSponsorship": false,
  "includeDescription": false,
  "newOnly": false,
  "maxJobsPerCompany": 25
}
```

# Actor output Schema

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

One row per job with the unified schema: title, locations, remote, department, employment type, salary text where the ATS provides it, posting date, links and optional description.

## `changes` (type: `string`):

New, closed and retitled jobs compared with the previous snapshot of the same watch name or task.

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

Per-company counts, skipped inputs with reasons, and totals.

# 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": [
        "notion",
        "linear"
    ],
    "maxJobsPerCompany": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/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": [
        "notion",
        "linear",
    ],
    "maxJobsPerCompany": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("deriverge/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": [
    "notion",
    "linear"
  ],
  "maxJobsPerCompany": 25
}' |
apify call deriverge/ashby-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deriverge/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/TuwpnJiAV9qJ2feF6/builds/x23s4Cl9gOo9Dknvk/openapi.json
