# Workday Job Board Scraper (`usestring/workday-jobs`) Actor

Collect job postings from any Workday careers site on myworkdayjobs.com.

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

## Pricing

from $0.75 / 1,000 results

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/platform/actors/running/actors-in-store#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

## Workday Job Board Scraper — any myworkdayjobs.com careers site

Collect job postings from any Workday-hosted careers site on `myworkdayjobs.com`. Give this Actor a
Workday careers-site URL, and it returns the board's postings with title, requisition ID, location
split into city, state and country, remote flag, posted date and apply URL.

A Workday careers site is a React shell whose served HTML contains no postings at all. This Actor
reads the tenant's own CXS job-search API — the same endpoint the site renders from — which answers
without a login. Workday rejects any page larger than 20 postings, so a full board is paginated 20 at
a time until the board's own reported total is reached.

No Workday account, login, API key or cookies are used. This Actor reads the public external careers
site that a logged-out visitor sees.

### What it returns

| Field | Type | Notes |
| --- | --- | --- |
| `jobId` | string | Workday's own requisition ID, as printed under the posting title — stable, use it to de-duplicate |
| `title` | string | |
| `tenant` | string | The Workday tenant the board is addressed by, e.g. `salesforce` |
| `location` | string | The posting's displayed location, verbatim. May read `"3 Locations"` when a posting is open in several offices |
| `city`, `state`, `country` | string | Resolved by what each part is rather than by its position, so `"Denver, CO, USA"` and `"USA, CA, Pleasanton"` both split correctly. Falls back to the primary office encoded in the posting's own URL when the displayed location is absent or reads `"3 Locations"` |
| `isRemote` | boolean | `true` when the location or Workday's `remoteType` names remote, virtual, home office or telecommute |
| `employmentType` | string | Workday's `timeType`, e.g. `"Full time"` |
| `postedAt` | string | Calendar date, `YYYY-MM-DD`. Reconstructed from Workday's relative label (`"Posted 4 Days Ago"`), which is the only posting date the search API publishes |
| `jobUrl` | string | Direct link to the posting |
| `boardUrl` | string | The careers site a person would open |
| `sourceUrl`, `collectedAt` | string | Provenance for every row |

### Input

```json
{ "boards": ["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"], "maxItems": 1000 }
```

| Field | Description |
| --- | --- |
| `boards` | Workday careers-site URLs on `myworkdayjobs.com`. Required, 1–100. |
| `maxItems` | Cap on dataset items. Default 1000, maximum 50,000. Free plans stop at 250 requests and 250 results — see below. |
| `concurrency` | Boards fetched in parallel. Default 5, maximum 10. |

The board page, a locale-prefixed board page such as `/en-US/External_Career_Site`, a single posting
URL and the CXS endpoint itself all collapse to the same Workday board and are fetched once rather
than billed several times. Pages are scheduled only while rows are still wanted, so a hundred boards
under a thousand-row cap fetch a thousand rows rather than a hundred boards in full.

### Use cases

- Tracking enterprise hiring across a watchlist of Workday careers sites
- Competitor headcount signals by location and remote status
- Filling an ATS, job board or talent CRM with live postings straight from the employer
- Recruiting lead lists filtered on `city`, `state`, `country` or `isRemote`
- Monitoring a board over time by re-running on a schedule and diffing on `jobId`

### Reliability

The CXS job-search API is structured JSON published by the Workday tenant itself, so there is no
markup contract to break and no model in the path.

Workday answers a rejected search with an error envelope that carries its own `httpStatus` inside a
200 response, so a failed board would otherwise look like a successful empty one. That envelope is
read and the board is reported as a failure instead.

Postings are de-duplicated on `jobUrl`, because a board whose reported total understates it hands
back page one again past the end rather than terminating.

A board that cannot be read is recorded in the run's `SUMMARY` under `failures` rather than silently
returning fewer rows, and a run where every board failed exits with an error.

### Frequently asked questions

**How do I find a company's Workday careers-site URL?** A Workday careers site looks like
`https://<tenant>.wd<N>.myworkdayjobs.com/<Board>` — for example
`https://salesforce.wd12.myworkdayjobs.com/External_Career_Site`. Open the company's "careers" or
"search jobs" link and copy the URL from the address bar; you can paste a single posting's URL too.

**Do I need a Workday account, API key or login?** No. This Actor reads the same unauthenticated CXS
job-search endpoint the public careers site renders from. No account, no cookies, no session.

**How many job postings does one request return?** 20. Workday answers `HTTP_400` to any larger page,
so a full board is always paginated 20 postings at a time.

**Does it work for any company on Workday?** Yes — any external careers site on `myworkdayjobs.com`.
The tenant and board are read out of the URL you supply, so nothing is hardcoded per company.

**Why is there no company name or department?** Workday publishes neither on any public endpoint. The
search response carries no company display name and the detail endpoint carries only the hiring legal
entity; department exists only as a facet that counts postings per category without naming the
category of any one posting. Both are left out rather than filled with something wrong. `tenant` is
the identity the board is addressed by.

**How accurate is `postedAt`?** It is a calendar date reconstructed from Workday's own relative label
against the run's clock, so `"Posted 4 Days Ago"` becomes an exact date. `"Posted 30+ Days Ago"` is
an open bound and is left `null` rather than dated 30 days back.

### Limitations

Search-result fields only: no job description body, no compensation, no application counts and no
recruiter contacts. No company display name and no department, for the reason above. `postedAt` is a
date rather than a timestamp, and is `null` for postings older than 30 days. Only
`myworkdayjobs.com` careers sites are accepted — a URL on any other host is rejected rather than
fetched.

### Free plan limit

Runs started from an Apify **free plan** stop at **250 requests and 250 results**, and the run
reports that it reached the limit. Any paid plan runs the full input and `maxItems` you set.

The limit exists because this Actor fetches through our own infrastructure, which Apify does not
cover for free-plan runs. It binds on requests as well as results so that a large input list cannot
spend those fetches for rows the run will not return.

# Actor input Schema

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

Workday careers-site URLs (…myworkdayjobs.com/…).

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

Global cap on dataset items. Runs started from an Apify free plan stop at 250 requests and 250 results; any paid plan runs the full amount.

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

Targets fetched in parallel.

## Actor input object example

```json
{
  "boards": [
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ],
  "maxItems": 1000,
  "concurrency": 5
}
```

# Actor output Schema

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

Collect job postings from any Workday careers site on myworkdayjobs.com.

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

Item count, failure count and every target that failed, with its error.

# 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 = {
    "boards": [
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("usestring/workday-jobs").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 = { "boards": ["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"] }

# Run the Actor and wait for it to finish
run = client.actor("usestring/workday-jobs").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 '{
  "boards": [
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ]
}' |
apify call usestring/workday-jobs --silent --output-dataset

```

## MCP server setup

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

```

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/1XGNFibgGqbfjK2mN/builds/Fb7ZVypfJe3e7y8na/openapi.json
