# Workable Jobs Scraper: Career Pages, Remote & Alerts (`wiltech/workable-jobs-scraper`) Actor

Open jobs from any Workable careers page (apply.workable.com) via its public job feed. Give company names or careers links; get every job with locations, hybrid/remote setting, department, description and alerts.

- **URL**: https://apify.com/wiltech/workable-jobs-scraper.md
- **Developed by:** [Wil Tech](https://apify.com/wiltech) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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.

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

## Workable Jobs Scraper

Get every open job from any **Workable careers page** (`apply.workable.com/{company}`) in one clean format, from Workable's public job feed. Each job comes with title, department, locations, country, hybrid/remote/on-site setting, employment type, experience level, posting date, apply link and full description.

Use it to **track who is hiring**, build **job boards and alerts**, find **sales leads from hiring signals**, or give an **AI agent** live jobs data.

### What you get

- **Every job in one request** per company, with the full description.
- **Hybrid, remote or on-site** as shown on the careers page.
- **One row per job:** jobs open in several cities are merged, with all cities listed.
- **Respects the employer's choices:** locations the employer hides on its careers page are not output.
- **New-job alerts:** schedule it daily and get only new jobs.

### How to use it

1. Add companies in **Companies**: `https://apply.workable.com/huggingface/`, `workable:huggingface`, a website or a name.
2. Optionally narrow the results with filters.
3. Run it and download as JSON, CSV or Excel, or connect to Google Sheets, Slack, Zapier or Make.

### Good to know

- Workable's public feed has no salary field, so `salary` is empty.
- A company name is confirmed with the company name Workable publishes; careers links are always exact.

### Filters

All filters run before results are saved, so you only pay for jobs you keep.

| Filter | Example |
| --- | --- |
| Job title contains | `engineer`, `sales` (matches the start of words: "engineer" finds "Engineering Manager") |
| Job title does not contain | `intern`, `senior` |
| Location contains | `London`, `Germany`, `Remote`, `US` |
| Workplace type | Remote, Hybrid, On-site, Not stated |
| Department or team contains | `Engineering`, `Sales` |
| Posted in the last N days | `7` |
| Only jobs that show a salary | on/off |

### New jobs only (alerts)

Turn on **Only new jobs since the last run** and schedule the Actor (for example every morning). The first run returns everything and sets the baseline; later runs return only jobs that weren't there before. Every job also carries `isNew` and `firstSeenAt`. Use **Watch list name** to keep separate alert lists.

### For AI agents and automations

- Every input has a sensible default except **Companies**, which is required.
- Results never come back empty without a reason: unmatched companies, missing boards, failed loads and "no jobs matched your filters" each produce a `recordType: "status"` row with a plain-language `message`. Status rows are free.
- A run summary (per company: boards found, confidence, jobs found and saved, notes) is saved to the key-value store as `OUTPUT`.
- `matchConfidence` on every job: `exact` (you gave the link), `high` (found on the company's own website, or confirmed by the employer name the job system publishes), `medium` (board name equals the company name but could not be confirmed).

### Output fields

| Field | Description |
| --- | --- |
| `id` | Stable ID: `provider:board:jobId`. Use it to deduplicate across runs. |
| `companyName`, `companySlug` | Company name and its board name in Workable |
| `title`, `department`, `team` | Role details, when Workable provides them |
| `location`, `locations` | Primary location and all listed locations |
| `countryCode`, `countryName` | ISO country code; null when unknown or when a job spans several countries |
| `workplaceType`, `isRemote` | `remote`, `hybrid`, `onsite` or `unspecified` |
| `employmentType` | `full-time`, `part-time`, `contract`, `internship`, `temporary`, `other` |
| `salary`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryText` | Pay range when published; null otherwise |
| `postedAt` | ISO date |
| `url`, `applyUrl` | Job page and application link |
| `requisitionId` | Company's requisition ID, when public |
| `description`, `descriptionHtml` | Full description as text and/or HTML |
| `isNew`, `firstSeenAt` | New-job tracking (`isNew` is null on the first run) |
| `companyInput`, `matchConfidence`, `scrapedAt` | Which input produced the job, how sure the match is, when it was collected |

### Pricing

Pay per result: **$2.00 per 1,000 jobs** saved, plus Apify's small per-run start fee. Filtered-out jobs and status records are free. Set a maximum cost per run in Apify Console and the Actor stops cleanly when it is reached.

### More job systems

Need several job systems in one run? [Career Site Jobs](https://apify.com/wiltech/career-site-jobs) reads 10 job systems (Workday, Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor and Breezy HR) with the same output format, and finds each company's board for you.

### Support

Something missing or wrong? Open an issue on the Issues tab with the company you tried; fixes are made based on requests.

Workable is a trademark of its owner. This Actor is independent and not affiliated with or endorsed by Workable Software Limited.

# Actor input Schema

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

One company per line: a careers link (https://apply.workable.com/huggingface/), a company name, a website, or workable:account (workable:huggingface).

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

Keep jobs whose title contains any of these words, e.g. engineer, sales, marketing. Matches the start of words, so "engineer" also finds "Engineering Manager". Leave empty for all jobs.

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

Drop jobs whose title contains any of these words, e.g. intern, senior.

## `locationKeywords` (type: `array`):

Keep jobs whose location matches any of these, e.g. London, Germany, Remote, or a 2-letter country code such as US.

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

Keep only these workplace types. Leave empty for all. "Not stated" covers jobs whose posting does not say.

## `departmentKeywords` (type: `array`):

Keep jobs whose department or team matches any of these, e.g. Engineering, Sales.

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

Keep jobs posted in the last N days. 0 means any date. Jobs with no posting date are kept.

## `requireSalary` (type: `boolean`):

Keep only jobs that publish a salary range.

## `onlyNewJobs` (type: `boolean`):

Return only jobs not seen in earlier runs of the same company list (or the same watch list name). Ideal for scheduled daily or weekly alerts. The first run returns everything and sets the baseline.

## `watchListName` (type: `string`):

Optional. Give a name to keep "new job" tracking separate from your other lists, or to keep it when you edit the company list. Without a name, tracking follows the exact company list.

## `descriptionFormat` (type: `string`):

Include the full job description as plain text, HTML, both, or not at all (faster, smaller results).

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

Stop reading a company's board after this many jobs. Large employers list thousands of jobs.

## `maxTotalJobs` (type: `integer`):

Stop the run after saving this many jobs in total. 0 means no limit. Your run's spending limit is always respected as well.

## `scanCompanyWebsites` (type: `boolean`):

When you give a website (stripe.com), read its careers page to find the exact job board. Respects the site's robots.txt. Turn off to only check job systems directly.

## `acceptUncertainMatches` (type: `boolean`):

When a company name only loosely matches a job board, include it anyway. Off by default so you never get another company's jobs by mistake; every job carries matchConfidence either way.

## `includeStatusRecords` (type: `boolean`):

Add a record (recordType "status", never charged) for each company that could not be matched or loaded, explaining why. Useful for automations and AI agents so a missing company is never silent.

## Actor input object example

```json
{
  "companies": [
    "https://apply.workable.com/huggingface/",
    "workable:epignosis",
    "Hugging Face"
  ],
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "locationKeywords": [],
  "workplaceTypes": [],
  "departmentKeywords": [],
  "postedWithinDays": 0,
  "requireSalary": false,
  "onlyNewJobs": false,
  "watchListName": "",
  "descriptionFormat": "text",
  "maxJobsPerCompany": 500,
  "maxTotalJobs": 0,
  "scanCompanyWebsites": true,
  "acceptUncertainMatches": false,
  "includeStatusRecords": true
}
```

# Actor output Schema

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

All open jobs that matched your filters, plus free status records for companies that need attention.

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

Per-company report: job boards found, match confidence, jobs found and saved, and notes.

# 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": [
        "https://apply.workable.com/huggingface/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wiltech/workable-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": ["https://apply.workable.com/huggingface/"] }

# Run the Actor and wait for it to finish
run = client.actor("wiltech/workable-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": [
    "https://apply.workable.com/huggingface/"
  ]
}' |
apify call wiltech/workable-jobs-scraper --silent --output-dataset

```

## MCP server setup

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