# Ashby Jobs Scraper (`lergassy/ashby-jobs-scraper`) Actor

\[$1.20/1K jobs] Scrape every open job from any company's Ashby board: title, department, location, country, remote / hybrid / on-site, salary min and max as numbers, date, full description, apply link. Filters, no login.

- **URL**: https://apify.com/lergassy/ashby-jobs-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.84 / 1,000 jobs

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** downloads every open job from the Ashby job boards of the companies you list. Give it company slugs (`openai`) or careers URLs (`https://jobs.ashbyhq.com/ramp`), press Start, and get one row per job: title, department, location, remote / hybrid / on-site, salary when the company publishes it, publish date, the full description, the job and apply links, and any recruiter emails written in the posting. Filter by title keywords, location, workplace and date. No login, no API key, no browser. Export JSON, CSV or Excel, schedule it, or call it from the API.

> This Actor is a focused entry point for the query "ashby jobs". It runs the same engine as **[Jobs API — Indeed, LinkedIn & career sites](https://apify.com/lergassy/jobs-api)**, which also reads Greenhouse, Lever, Ashby, Workable and SmartRecruiters boards and searches Indeed and LinkedIn. Use Jobs API when you need several systems or job boards in one run.

### What does the Ashby jobs scraper do?

Ashby is the applicant-tracking system behind the careers pages of thousands of companies. Every company on Ashby has a public job board (`jobs.ashbyhq.com/<slug>`), and Ashby serves that board through a public JSON API (api.ashbyhq.com). This Actor reads that API for each company in your list — one request returns the whole board, with descriptions — and turns it into clean rows in the same format for every company.

- **Whole boards in seconds.** A company with 800 open roles is one request, not 800 page visits.
- **Filters applied for you:** title keywords, locations, remote / hybrid / on-site, posted within a day / week / month or after a fixed date. Jobs come newest first, so a per-company cap keeps the freshest ones.
- **Normalised fields** you can sort and join: ISO dates, `isRemote` and `workplaceType`, `salaryMin` / `salaryMax` as numbers.
- **Nothing silently disappears.** A company slug that does not exist on Ashby gets its own free error row saying so; a run where the filters left nothing gets a free row explaining which filter to widen.

**What it does not do:** it does not search *all* Ashby companies at once — you give the companies. There is no global directory of Ashby boards in this Actor. If you need a keyword search across the whole job market, use [Jobs API](https://apify.com/lergassy/jobs-api) (Indeed + LinkedIn).

### What data does it return?

| Field | Example |
|---|---|
| `source`, `board`, `id`, `url`, `applyUrl` | ashby · ramp · d84bbf19-… · https://jobs.ashbyhq.com/ramp/d84bbf19-… · …/application |
| `title`, `company`, `department` | Account Manager | Mid-Market · ramp · Sales |
| `location`, `allLocations`, `city`, `region`, `country` | New York, NY (HQ) · \["New York, NY (HQ)", "San Francisco, CA", "Remote (US)"] · New York City · NY · USA |
| `workplaceType`, `isRemote` | remote · true (Ashby's own field: remote / hybrid / onsite) |
| `employmentType`, `jobTypes` | fulltime · \["fulltime"] |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryText` | 190000 · 330000 · USD · year · "$190K – $330K • Offers Equity • Multiple Ranges" |
| `postedAt` | 2026-09-23T16:15:40.412Z (published) |
| `description`, `descriptionHtml` | full text and HTML |
| `emails`, `phones`, `companyDomain` | addresses written in the posting · domain from the apply link when it is the company's own site |
| `query`, `scrapedAt` | (empty for boards) · run time |

- **Salary as numbers**: taken from Ashby's structured compensation (the salary component: min, max, currency, interval), with Ashby's own summary kept in `salaryText`. When a job has several ranges (by location or level), Ashby's summary spans them — lowest minimum to highest maximum — and `salaryText` says "Multiple Ranges".
- **Remote**: Ashby's raw API marks hybrid jobs as `isRemote: true` too (checked on OpenAI, Notion and Ramp boards). Here `isRemote` follows Ashby's workplace field, so a hybrid job is never returned as remote. When a company leaves the workplace field empty, a job counts as remote if one of its locations says "Remote".
- **Company** is the board slug (`openai`), because Ashby's public job-board API does not return the display name.

### How much does it cost?

**$1.20 per 1,000 jobs** ($0.0012 per job row) on the Free plan, down to $0.84 per 1,000 on higher Apify plans. No fee per run, per company or per request. Error rows (unknown company, a board that did not answer) and the "nothing matched" explanation row are free. Jobs removed by your filters are not charged — you pay only for rows in the dataset.

Example: 10 companies × 150 open jobs = 1,500 rows = $1.80 on the Free plan. Filter to "engineer" + "remote" and you pay only for those rows.

### How to scrape Ashby jobs

1. Open the **Input** tab.
2. Put company slugs or careers URLs into **🏢 Companies on Ashby**, one per line. The slug is the part after the board domain: in `https://jobs.ashbyhq.com/ramp` it is `ramp`.
3. Optional: add **Title keywords**, **Locations**, **Workplace** and **Posted within**.
4. Press **Start**, then download the results from the **Output** tab, or read them through the API.

An empty API call works too: with no companies, the Actor returns a demo — the 20 newest jobs each from openai, ramp and linear.

### ⬇️ Input

```json
{
    "companies": ["openai", "https://jobs.ashbyhq.com/ramp", "linear"],
    "titleKeywords": ["engineer", "product"],
    "workplace": "remote",
    "locations": ["United States", "US"]
}
```

| Field | Default | What it does |
|---|---|---|
| `companies` | demo | Ashby board slugs or careers URLs. A URL from another supported system (Greenhouse, Lever, Ashby, Workable, SmartRecruiters) also works |
| `titleKeywords` | empty | Keep jobs whose title or department contains one of the words |
| `locations` | empty | Keep jobs whose location contains one of the texts |
| `workplace` | `any` | `remote`, `hybrid` or `onsite` |
| `postedWithin` / `postedAfter` | any | Drop older jobs (`day`, `3days`, `week`, `month`, or a `YYYY-MM-DD` date) |
| `maxJobsPerCompany` | all | Cap per board after the filters, newest first |
| `maxItems` | 100,000 | Cap for the whole run |
| `includeDescription` | `true` | Full description text and HTML |
| `includeContacts` | `true` | Emails and phones found in the posting, free |
| `concurrency`, `proxyConfiguration` | 5, off | Boards read at once; no proxy needed — if a board refuses a direct request it is retried once through Apify Proxy |

### ⬆️ Output

One row per job with `"type": "job"`. Free rows with `"type": "error"` explain a company that could not be read or a search that matched nothing. Download as JSON, CSV, Excel or XML, or get it from the API (`/datasets/{id}/items`). A JSON summary of the run is saved as `STATS` in the key-value store.

### Use cases

- **Job boards and aggregators**: pull the full, current list of roles from the companies you track, every day.
- **Recruiting and sourcing**: watch competitors' and target companies' openings by department and location.
- **Sales and lead generation**: a company hiring five sales engineers is a company buying sales tools — filter by title and push to your CRM.
- **Market and salary research**: compare published salary ranges by role, location and company.
- **Job alerts**: schedule a daily run with `postedWithin: "day"` and send new postings to Slack, email or a Google Sheet.

### Tips

- Many companies use different systems for different brands. If a slug returns "not found", open the company's careers page and look at the job links: `greenhouse.io`, `lever.co` and `ashbyhq.com` tell you which system and slug to use.
- For a daily feed use **Schedules** with `postedWithin: "day"` (or `postedAfter` set to yesterday) so you pay only for new jobs.
- Everything in this Actor is available from the API and to AI agents through the Apify MCP server.

### ❓ FAQ

**Is it legal?** It reads job postings that companies publish publicly on purpose, through the public API Ashby provides for job boards. Check your own use against the laws that apply to you, especially if you process personal data such as recruiter emails.

**Why is a company missing jobs I see on its website?** Some companies list a part of their roles on another system or hide internal postings from the public board. This Actor returns exactly what the public Ashby board shows.

**Can I search all Ashby companies by keyword?** Not with this Actor — you give the companies. For a market-wide keyword search use [Jobs API](https://apify.com/lergassy/jobs-api).

### Your feedback

Found a bug or a board that does not parse well? Open an issue on the **Issues** tab — we fix reports quickly.

# Actor input Schema

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

One company per line: its Ashby board slug (<code>openai</code>) or the careers URL (<code>https://jobs.ashbyhq.com/ramp</code>). The slug is the part after the board domain in the company's Ashby job-board URL. Every open job on each board is returned (newest first), then the filters below are applied. Empty = a demo with openai, ramp, linear (20 jobs each).

## `titleKeywords` (type: `array`):

Keep only jobs whose title or department contains one of these words (case-insensitive): <code>engineer</code>, <code>sales</code>, <code>product manager</code>. Empty = all jobs.

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

Keep only jobs whose location contains one of these texts (case-insensitive): <code>London</code>, <code>United States</code>, <code>Remote</code>, <code>Germany</code>. Matched against the location as the company wrote it plus country and city fields. Empty = any location.

## `workplace` (type: `string`):

Uses Ashby's own workplace field (Remote / Hybrid / On-site). Note: Ashby marks hybrid jobs as "isRemote" too — this filter does not, a hybrid job is never returned as remote.

## `postedWithin` (type: `string`):

Drop jobs first published earlier than this. Ashby gives the published date.

## `postedAfter` (type: `string`):

<code>YYYY-MM-DD</code>. Use instead of "Posted within" for a fixed date (handy for daily schedules).

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

Cap per board after the filters, newest first. Leave empty for every matching job (big boards have 500–900 open roles); the form starts at 20 so a first try stays cheap.

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

Stop after this many job rows in total.

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

Description as plain text and HTML. Turn off for a lighter export with titles, locations and links only.

## `includeContacts` (type: `boolean`):

Recruiter emails and phone numbers written in the job description, plus the company domain from the apply link. Free.

## `concurrency` (type: `integer`):

How many boards are read at once.

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

Not needed: Ashby's public job-board API answers direct requests. If a board ever refuses, that one request is retried through Apify Proxy automatically.

## Actor input object example

```json
{
  "companies": [
    "openai",
    "ramp",
    "linear"
  ],
  "workplace": "any",
  "postedWithin": "any",
  "maxJobsPerCompany": 20,
  "maxItems": 100000,
  "includeDescription": true,
  "includeContacts": true,
  "concurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per job: source, title, company, company website and size, location, remote/hybrid, job type, salary as numbers, posting date, description, apply link, skills, emails and phones found in the posting.

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

JSON counters for the run: rows delivered, filtered out, errors and request statistics.

# 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",
        "linear"
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/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",
        "linear",
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

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

```

## MCP server setup

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