# Workable Jobs Scraper & Change Monitor (`luminar/workable-jobs-change-monitor`) Actor

Find public Workable jobs by role and location, export complete job details, and track changes across repeat searches and company watch lists.

- **URL**: https://apify.com/luminar/workable-jobs-change-monitor.md
- **Developed by:** [Luka](https://apify.com/luminar) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 job records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Turn Workable searches and company job pages into a useful job catalogue, then keep it current with repeat checks.

- **Find jobs:** search by role, location, posting date and work arrangement.
- **Export the details:** employer, locations, description, requirements, benefits and application link.
- **See what changed:** stable job IDs and separate new, updated and verified absence records.

You receive `job`, `change` and `coverage` rows. A job identifies the role and employer; a coverage row tells you how much of the requested source was checked.

### 🚀 Start in 60 seconds

1. Keep **Get current jobs**, or enter a role and location.
2. Leave **Maximum current jobs** at 20 for a small first export.
3. Start the Actor, then open **Jobs, changes and coverage**.

A successful 20-job collection costs **$0.0225**: $0.0045 for the verified collection plus $0.0009 for each current job. The same prices apply across plans. Export as JSON, CSV, Excel or XML.

### 🎯 Choose the right workflow

| Goal | Workflow | Input |
|---|---|---|
| Find current roles | Get current jobs | Role and location, or public Workable search/company URLs |
| Inspect specific roles | Get job details | Individual `https://jobs.workable.com/view/...` URLs |
| Compare repeat checks | Track changes | The same searches or company URLs and watch name, run sequentially |

Pasted URLs take priority over the default keyword search. Search filters apply to searches; explicit company pages retain the company's complete public job scope. The Actor supports `jobs.workable.com` search, company and job pages. A company watch list is supplied by you; the Actor does not discover every employer using Workable.

### 📦 What you get

Current job rows include `stableId`, `jobId`, `title`, `company`, employer URLs, location components, work arrangement, employment type, posting/update dates, source publication state, full HTML/plain text content, requirements, benefits and application URL. Optional fields are `null` when not published.

Change rows add `changeId`, `changeKind` and the previous content fingerprint. `NEW` means first observed in this watch, not necessarily first published today. `UPDATED` means a source-published job field changed. `NO_LONGER_LISTED` means a saved job left a completely checked company listing. `LEFT_SEARCH_RESULTS` means it left a fully checked search scope; neither event claims that someone was hired. An inaccessible source or a cap cannot produce an absence event.

Coverage rows show `sourceJobs`, `matchedJobs`, `deliveredJobs` and `coverageStatus` for each target. Keep these rows when assessing completeness. Filter `recordType=job` in downstream tools when you only need current jobs.

![Workable jobs output sample](https://api.apify.com/v2/key-value-stores/DJgPR6wwS2tIaLDQW/records/workable_jobs_change_monitor--35c31a9c6b0cab53-output.png)

### 🎛️ Input guide

| Setting | Use |
|---|---|
| Role or keywords | Workable's public content search; matches can occur in the description |
| Location | Country, region or city; `remote` selects remote roles |
| Workable URLs | Up to 50 public search, company or job URLs; overrides the default search |
| Posting date / Work arrangement / Employment type | Narrow search results |
| Include full text | Controls export size; it does not change the per-job price |
| Watch name | Keeps independent repeat-monitoring baselines separate |
| First monitoring run | Save a starting list, or also emit current jobs as NEW |
| Maximum current jobs | 1–10,000 unique current jobs across the run |
| Collection time limit | 10–210 seconds; allow at least 60 more seconds for final delivery |
| Maximum buyer charge | Guard for the requested workload; also respect the platform spending limit |

For monitoring, repeat runs sequentially with the same watch name, URLs, filters and full-text setting. A new scope starts a new baseline. The saved state supports up to 10,000 jobs. Current rows are still returned and charged on unchanged checks; the change rows make comparison easier. An interrupted delivery must be recovered in its original run before the watch continues.

### 💰 Pricing

| Event | Price |
|---|---:|
| Verified collection, once per run | $0.0045 |
| Each verified current job | $0.0009 |
| Each verified saved absence | $0.0009 |
| NEW and UPDATED change rows, coverage rows | Included |

Examples: 1 job **$0.0054**; 20 jobs **$0.0225**; 100 jobs **$0.0945**; 1,000 jobs **$0.9045**. A trustworthy empty collection costs $0.0045. A source failure with no verified result is free. If other targets succeed, their verified jobs and the one collection fee apply. Platform usage pass-through is off; no additional source or platform usage charge is added by this Actor.

Monitoring can return current jobs plus saved absences, so set the spending cap for both. At the maximum, 10,000 current jobs plus 10,000 distinct absences cost **$18.0045**. This is an upper bound, not an expected run. Optional description fields do not add an event.

### ✅ Coverage you can trust

`COMPLETE` means the requested target was exhausted and its records verified. `EMPTY_CONFIRMED` means a valid source returned no matching jobs. `CAPPED` means a result, time or output-size limit stopped collection. `PARTIAL` combines trusted results with unsuccessful targets. `FAILED` means that target could not be verified; `NOT_VISITED` means an earlier run limit prevented its check.

The export has a 30 MB data limit and a 256 KB limit per normalized job. Large descriptions may reach a limit before the job-count maximum. A collection may change while it is being read; inconsistent totals keep absence reporting disabled. No query is silently broadened when it returns zero jobs.

### 🔌 API and automation

Use the Actor's API tab to run `luminar/workable-jobs-change-monitor` and read its Dataset. A small input is:

```json
{"keyword":"software","location":"United States","maxJobs":20}
```

For sequential monitoring:

```json
{"workflow":"monitor","keyword":"product manager","location":"remote","stateNamespace":"remote-product-jobs","maxJobs":100,"maxBuyerChargeUsd":1}
```

Use `stableId` to update a current-job table and `changeId` to deduplicate change observations. Keep coverage separate from job records in your destination. Apify integrations can connect the Dataset to your own workflow; no preconfigured destination or public template is included.

### ⚠️ Not yet supported

- Private hiring pipelines, applicant information, application submission or account data.
- `apply.workable.com` career pages, employer subdomains, or other applicant-tracking systems. Use the corresponding public `jobs.workable.com` company/job page.
- Guaranteed collection of the entire Workable catalogue, inference of hires or salaries, or absence claims from incomplete searches.
- Simultaneous runs sharing one watch. Use sequential checks and inspect coverage before relying on changes.

### ❓ FAQ and support

**Why do I see a matching job without the keyword in its title?** Workable searches job content too. Review the description and source link.

**Are unchanged jobs free?** Current verified job observations are charged on every run. NEW/UPDATED change rows are included, and saved absences have their own small result charge.

**Why is an optional field empty?** Employers do not publish every field. Empty secondary metadata stays null; the Actor does not invent it.

**Can a missing job prove a hire?** No. Source absence is a listing observation, not evidence of a hire.

For support, share the run ID and expected public job/search URL through the Actor's Issues tab. Do not include credentials or applicant information.

# Actor input Schema

## `workflow` (type: `string`):

Export current jobs, inspect job URLs, or compare repeated checks.

## `keyword` (type: `string`):

Used when no URLs are supplied. Workable searches the job content; matches need not contain the phrase in the title.

## `location` (type: `string`):

Country, region or city for search. Use remote for remote roles. Not applied to explicit company or job URLs.

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

Optional jobs.workable.com search, company or individual job URLs. These take priority over the role/location search. Up to 50 distinct targets.

## `postedDate` (type: `string`):

Filter search results by the published date. Individual jobs and company pages retain their complete source scope.

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

Search only: choose the source-published work arrangement.

## `employmentType` (type: `string`):

Search only: full-time, part-time, contract or another source-published type.

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

Include descriptions, requirements and benefits in HTML and plain text. Turning this off makes the export smaller; job pricing stays the same.

## `stateNamespace` (type: `string`):

Track changes only. Keep the same watch name and search scope for sequential repeat runs. Use a new name to start a separate baseline.

## `firstRunBehavior` (type: `string`):

Save the starting job list, or also emit NEW observations for its current jobs. Current verified jobs are charged in both cases.

## `maxJobs` (type: `integer`):

Maximum unique current jobs for the whole run, from 1 to 10,000. Saved absences can add up to 10,000 separately priced records. A cap never proves a job disappeared.

## `maxRuntimeSecs` (type: `integer`):

Source collection limit, 10–210 seconds. Allow at least 60 additional seconds in the run timeout for final delivery. The default platform timeout is 300 seconds.

## `maxBuyerChargeUsd` (type: `number`):

Preflight checks the requested job limit and possible saved absences against this cap. Increase it for larger jobs. Also set a sufficient platform spending limit.

## Actor input object example

```json
{
  "workflow": "collect",
  "keyword": "software",
  "location": "United States",
  "startUrls": [],
  "postedDate": "anytime",
  "workplace": "all",
  "employmentType": "all",
  "includeDescription": true,
  "stateNamespace": "default",
  "firstRunBehavior": "seed_only",
  "maxJobs": 20,
  "maxRuntimeSecs": 180,
  "maxBuyerChargeUsd": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

Open jobs, changes and target coverage.

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

Verified job count, coverage and expected buyer charge.

# 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 = {
    "workflow": "collect",
    "keyword": "software",
    "location": "United States",
    "startUrls": [],
    "postedDate": "anytime",
    "workplace": "all",
    "employmentType": "all",
    "includeDescription": true,
    "stateNamespace": "default",
    "firstRunBehavior": "seed_only",
    "maxJobs": 20,
    "maxRuntimeSecs": 180,
    "maxBuyerChargeUsd": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("luminar/workable-jobs-change-monitor").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 = {
    "workflow": "collect",
    "keyword": "software",
    "location": "United States",
    "startUrls": [],
    "postedDate": "anytime",
    "workplace": "all",
    "employmentType": "all",
    "includeDescription": True,
    "stateNamespace": "default",
    "firstRunBehavior": "seed_only",
    "maxJobs": 20,
    "maxRuntimeSecs": 180,
    "maxBuyerChargeUsd": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("luminar/workable-jobs-change-monitor").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 '{
  "workflow": "collect",
  "keyword": "software",
  "location": "United States",
  "startUrls": [],
  "postedDate": "anytime",
  "workplace": "all",
  "employmentType": "all",
  "includeDescription": true,
  "stateNamespace": "default",
  "firstRunBehavior": "seed_only",
  "maxJobs": 20,
  "maxRuntimeSecs": 180,
  "maxBuyerChargeUsd": 1
}' |
apify call luminar/workable-jobs-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,luminar/workable-jobs-change-monitor"
        }
    }
}

```

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/TOqCRN5fOqu4AfPb3/builds/v0MFkQaN2xZE5U2pF/openapi.json
