# Ashby Jobs Scraper — Job Boards & Postings (`tortuga/ashby-jobs-scraper`) Actor

Scrape Ashby jobs from any Ashby job board (jobs.ashbyhq.com) or company careers site built on Ashby: all job postings with title, department, team, location, remote flag, compensation, posted date, full description and apply URL. Public posting API, no login or API key.

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

## Pricing

$1.50 / 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.

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 — Job Boards & Postings

Scrape Ashby jobs from any Ashby job board (`jobs.ashbyhq.com/<company>`) or company careers site built on Ashby. The actor reads Ashby's **public job posting API**, the same feed the board itself loads, and returns one clean row per job posting: title, company, department and team, locations with city, region and country, remote / hybrid / on-site, employment type, **compensation** (salary range, currency, period and Ashby's own summary such as "$257K – $335K • Offers Equity") whenever the company publishes it, posted date, job and apply URLs, and the **full description** as text and HTML.

No login, no API key, no browser: one request per board returns every listed job with its description, so even OpenAI's board (800+ postings) is scraped in a few seconds for a fraction of a cent of platform usage.

Typical uses: job alerts for the Ashby-based companies you follow, hiring signals for sales and recruiting (who is hiring which roles, where, at what pay), salary benchmarking, feeding a job board, a spreadsheet or an LLM pipeline.

### What data does Ashby Jobs Scraper extract?

| Field | Description |
|---|---|
| `jobId`, `atsJobId` | Stable unique id `ashby:<board>:<posting id>` and Ashby's own posting id (a UUID) |
| `companyName`, `companySlug`, `careerSiteUrl` | Company as shown on the board, the board name (`openai`) and the board URL |
| `title`, `department`, `team` | Job title and the department / team the company files it under in Ashby |
| `location`, `locations` | Primary location as the company writes it, plus every secondary location |
| `city`, `region`, `country`, `countryCode` | From the posting's postal address when Ashby has one; otherwise the country is read from the location text (ISO code) |
| `isRemote`, `isHybrid`, `workplaceType` | Ashby's remote flag and workplace type, normalised to `remote` / `hybrid` / `onsite` (null when the company set none) |
| `employmentType` | `Full-time`, `Part-time`, `Contract`, `Internship`, `Temporary` |
| `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salarySource` | Pay range from Ashby's compensation block (`salarySource: "ats"`), e.g. 257000 – 335000 USD per `year`; if the company publishes no structured pay but writes a range in the description, that range is used (`"description"`) |
| `compensationSummary` | Ashby's compensation summary line, e.g. `$257K – $335K • Offers Equity` |
| `postedAt` | When the posting was published (UTC, ISO 8601) |
| `url`, `applyUrl` | The job page and the application form on jobs.ashbyhq.com |
| `description`, `descriptionHtml` | Full description as readable text and as HTML (with **Include full job description**, on by default) |
| `sourceUrl`, `scrapedAt` | Which input produced the job, and when |
| `changeType` | `new` in monitoring mode (see below) |

Companies decide what they fill in: in a sample of 810 OpenAI postings 80% carried a salary range, while Linear publishes none; `city` / `region` are empty when a company only names a region ("Europe", "North America").

### How to scrape Ashby jobs

1. Paste one or more URLs into **Ashby job board or careers page URLs**, e.g. `https://jobs.ashbyhq.com/openai`, or list board names under **Ashby board names** (`openai`, `linear`, `ramp`): the name is the part after `jobs.ashbyhq.com/`.
2. Optional filters: **Title keywords**, **Locations**, **Departments / teams**, **Remote jobs only**, **Posted within (days)**, **Max jobs per board**.
3. Click **Start**. Jobs appear in the **Output** tab, newest first per board; export JSON, CSV or Excel, or read them through the API.

### Which Ashby URLs work

- A job board: `https://jobs.ashbyhq.com/openai`
- A single job or application page: `https://jobs.ashbyhq.com/openai/8fb1615c-…` (the whole board is scraped)
- An embed or posting-API URL: `https://jobs.ashbyhq.com/linear?embed=js`, `https://api.ashbyhq.com/posting-api/job-board/linear`
- A company careers page or homepage on its own domain, e.g. `https://linear.app/careers`: the actor opens the page, counts the Ashby board links, iframes and embed scripts on it and picks the board mentioned most; if the page has none it follows the "Careers" / "Jobs" link and tries `/careers` and `/jobs` (at most 4 pages per site). Sites that do not use Ashby are reported in the run's `SUMMARY` (Storage → Key-value store) under `sitesWithoutAshbyBoard` and cost nothing; a misspelled board name shows up under `boardsNotFound`.

### Input example

```json
{
  "startUrls": [
    { "url": "https://jobs.ashbyhq.com/openai" },
    { "url": "https://linear.app/careers" }
  ],
  "boards": ["ramp", "notion"],
  "keywords": ["engineer", "product manager"],
  "locations": ["San Francisco", "London", "Remote"],
  "postedWithinDays": 30,
  "includeDescription": true,
  "maxItemsPerCompany": 50,
  "maxItems": 200
}
```

### Output example

```json
{
  "jobId": "ashby:openai:8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3",
  "atsJobId": "8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3",
  "ats": "ashby",
  "companyName": "OpenAI",
  "companySlug": "openai",
  "title": "Technical Program Manager, Compute Infrastructure",
  "department": "Technical Program Management",
  "team": "Technical Program Management",
  "location": "San Francisco",
  "locations": ["San Francisco"],
  "city": "San Francisco",
  "region": "California",
  "country": "United States",
  "countryCode": "US",
  "isRemote": false,
  "isHybrid": false,
  "workplaceType": null,
  "employmentType": "Full-time",
  "salaryText": "$257K - $335K",
  "salaryMin": 257000,
  "salaryMax": 335000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salarySource": "ats",
  "compensationSummary": "$257K – $335K • Offers Equity",
  "postedAt": "2026-03-12T16:38:15Z",
  "url": "https://jobs.ashbyhq.com/openai/8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3",
  "applyUrl": "https://jobs.ashbyhq.com/openai/8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3/application",
  "careerSiteUrl": "https://jobs.ashbyhq.com/openai",
  "description": "About the Team\n\nThe compute infrastructure team runs the GPU fleet and large-scale compute clusters that serve the models backing ChatGPT and the API ...",
  "descriptionHtml": "<h3><strong>About the Team</strong></h3><p>The compute infrastructure team runs ...</p>",
  "sourceUrl": "https://jobs.ashbyhq.com/openai",
  "scrapedAt": "2026-11-01T18:48:41Z"
}
```

### Does it need a login or API key

No. Ashby publishes every customer's job board through a public posting API so companies can show their jobs on their own websites; the actor calls that feed (`api.ashbyhq.com/posting-api/job-board/<name>`) and the public board page for the company's display name. No account, no API key, no cookies, no browser. Only postings the company has listed publicly are returned: unlisted and internal postings, candidate data and anything behind a login are never touched.

### Monitor new Ashby jobs on a schedule

Turn on **Only new jobs (monitoring)**, save the input as a task and add a Schedule (Apify Console → Schedules), e.g. every morning. Each run remembers which jobs earlier runs of the same input returned and outputs only the jobs that are **new** since then, marked `changeType: "new"`; jobs seen before are not output and not charged. With **Max jobs per board** set, the watch covers that many newest jobs per board. Use **Monitoring key** to keep several schedules on the same boards apart. This is the cheapest way to get job alerts or hiring signals for a list of Ashby-based companies: a daily run of ten boards with nothing new costs you nothing.

### Pricing

Pay per event, no subscription: **$0.0015 per job** saved, with all fields above, the full description and the compensation data included, and the Apify platform usage already included in that price. 1,000 Ashby jobs cost $1.50. Boards that do not exist and sites without an Ashby board cost nothing; monitoring runs charge only for new jobs.

### Proxy note

Ashby's API is public and answers direct requests from Apify in well under a second, so by default the actor uses no proxy. Turn on Apify Proxy (datacenter) only if a run log shows 403 or 429 answers. No residential proxy and no Unblocker are ever needed.

### Integrations and API

Use the results in Make, Zapier, n8n, Google Sheets, Airtable or your CRM, or call the actor from Python / Node.js with the Apify client (see the **API** tab). A Schedule plus monitoring gives you a daily feed of new jobs at your target companies.

### Is it legal to scrape Ashby job boards

The actor reads only job postings that companies publish openly on their Ashby job boards, through the public posting API Ashby provides for exactly that purpose. It does not log in, does not collect candidate, applicant or employee data, and does not access anything hidden or internal. Recruiter names that a company chooses to print in a job description stay part of that description. You are responsible for how you use the data and for complying with Ashby's and the companies' terms and with applicable law (e.g. the GDPR).

### Support

A board that does not work, a missing field, or a company site whose Ashby board is not detected? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

## `startUrls` (type: `array`):

Ashby job boards (https://jobs.ashbyhq.com/openai), a single Ashby job or application URL (its whole board is scraped), Ashby posting-API URLs, or a company careers page / homepage such as https://linear.app/careers: the actor opens it and finds the Ashby board in its links, iframes and embed scripts (it also follows the Careers/Jobs link and tries /careers and /jobs, 4 pages at most).

## `boards` (type: `array`):

Optional: Ashby board names you already know, i.e. the part after jobs.ashbyhq.com/, e.g. openai, linear, ramp (ashby:openai and full board URLs work too). Via the API you can also pass objects such as {"slug": "openai", "companyName": "OpenAI"} to set the company name yourself.

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

Keep only jobs whose title contains at least one of these words or phrases (case-insensitive), e.g. engineer, sales, "product manager". Leave empty for all jobs.

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

Keep only jobs whose location text, secondary locations, city, region or country contains one of these, e.g. London, Germany, US, Remote. Leave empty for all locations.

## `departments` (type: `array`):

Keep only jobs whose Ashby department or team contains one of these, e.g. Engineering, Sales.

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

Keep only jobs Ashby marks as remote (workplace type Remote) or whose location says Remote.

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

Keep only jobs published in the last N days (Ashby's exact publishedAt timestamp).

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

Add the full job description as plain text and HTML. Ashby sends it with the job list, so it costs no extra request and no extra charge; turn it off only to keep the dataset small.

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

Stop after this many jobs in total. Keeps cost predictable.

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

Optional cap per Ashby board (newest jobs first). With monitoring on, it is the number of newest jobs watched per board.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this input returned and output only jobs that are new since then. Use with a Schedule; jobs seen before are not output and not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same input stay separate; defaults to a key derived from the input.

## `proxyConfiguration` (type: `object`):

Not needed: Ashby's job-board API is public and direct requests from Apify are fastest. Turn on Apify Proxy (datacenter) only if a run log shows 403/429 answers. No residential proxy or Unblocker is ever needed.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://jobs.ashbyhq.com/openai"
    },
    {
      "url": "https://jobs.ashbyhq.com/linear"
    }
  ],
  "remoteOnly": false,
  "includeDescription": true,
  "maxItems": 20,
  "maxItemsPerCompany": 10,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://jobs.ashbyhq.com/openai"
        },
        {
            "url": "https://jobs.ashbyhq.com/linear"
        }
    ],
    "maxItems": 20,
    "maxItemsPerCompany": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/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 = {
    "startUrls": [
        { "url": "https://jobs.ashbyhq.com/openai" },
        { "url": "https://jobs.ashbyhq.com/linear" },
    ],
    "maxItems": 20,
    "maxItemsPerCompany": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/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 '{
  "startUrls": [
    {
      "url": "https://jobs.ashbyhq.com/openai"
    },
    {
      "url": "https://jobs.ashbyhq.com/linear"
    }
  ],
  "maxItems": 20,
  "maxItemsPerCompany": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call tortuga/ashby-jobs-scraper --silent --output-dataset

```

## MCP server setup

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