# Workday Jobs Scraper & API – Any Career Site, New Job Alerts (`pharaoh_data/workday-jobs-scraper`) Actor

Scrape jobs from any Workday career site (myworkdayjobs.com) with country, title, and keyword filters. Get descriptions, locations, dates, and apply links, plus new, updated, and closed jobs between runs for alerts and hiring signals.

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

## Pricing

from $1.50 / 1,000 job results

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

## Workday Jobs Scraper & API – Any Career Site, New Job Alerts

### Every job from any Workday career site, plus what changed since your last run

Paste the career-site URLs of the companies you care about: any `*.myworkdayjobs.com` or `myworkdaysite.com` site, such as NVIDIA, Salesforce, Intel, Adobe, or Mastercard. You get clean job records with **titles, all locations, ISO country codes, posting dates, requisition IDs, apply links, and full descriptions**.

Turn on change tracking and every scheduled run tells you which jobs are **new, updated, or closed**. That's a ready-made feed for job boards, recruiting alerts, and hiring-signal tools.

**Built for:**

- **Job boards and aggregators** that need fresh, deduplicated jobs from enterprise employers on Workday.
- **Recruiters and talent-intelligence teams** who want to know the day a target company opens or closes a role.
- **B2B sales teams** who use new hiring as a buying signal (for example, a company starts hiring data engineers in Germany).
- **Analysts and investors** tracking hiring velocity by company, country, or team.

### Why this Workday scraper

|                                   |                                                                                                                                                                                                                                   |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Country filter on the site**    | Ask for `Germany`, `AE`, or `"Saudi Arabia"`. The Actor finds each site's own location filter (Workday names it differently per site) and applies it before downloading, so a 2,000-job site returns only the jobs you asked for. |
| **New, updated, and closed jobs** | Each job is labelled against the previous run of the same monitor. Closed jobs are reported only when a site's full listing was read, so a truncated run never produces false closures.                                           |
| **Fast scheduled runs**           | In "Changes only" mode, detail pages are read only for new and updated jobs. A repeat run over five large employers took 11 seconds instead of 46.                                                                                |
| **Real countries**                | ISO 3166-1 codes from Workday's own job data, plus location parsing that keeps "US, CA" as California, not Canada.                                                                                                                |
| **Any URL form**                  | A career-site URL, a locale URL (`/en-US/...`), a job link, or a `myworkdaysite.com/recruiting/...` URL all work.                                                                                                                 |
| **Polite and compliant**          | robots.txt is checked for every site, there's a per-site rate limit (2 requests per second by default), and no proxies or logins are used. Contact details inside descriptions are redacted by default.                           |

### Quick start

1. Open a company's careers page. If its job links go to `something.wd5.myworkdayjobs.com/...`, copy that URL.
2. Paste one or more URLs under **Workday career-site URLs**.
3. Optionally add **Countries**, **Search text**, titles, locations, or keywords.
4. Run. To monitor, save it as a task with a schedule (for example daily) and switch **Output** to **Changes only**.

```json
{
    "careerSiteUrls": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
    ],
    "countries": ["Germany", "United Arab Emirates", "Saudi Arabia"],
    "searchText": "",
    "jobTitles": [],
    "postedWithinDays": 0,
    "maxJobsPerSite": 500,
    "includeDescriptions": true,
    "trackChanges": true,
    "outputMode": "changes",
    "monitorId": "enterprise-gulf-germany"
}
```

### Output

```json
{
    "jobId": "workday:example:external:Solutions-Architect---AI--Middle-East_JR1000001",
    "company": "Example",
    "hiringEntity": "Example Technologies FZ-LLC",
    "siteUrl": "https://example.wd5.myworkdayjobs.com/External",
    "title": "Solutions Architect - AI, Middle East",
    "location": "United Arab Emirates, Dubai / Saudi Arabia, Riyadh",
    "locations": ["United Arab Emirates, Dubai", "Saudi Arabia, Riyadh"],
    "country": "AE",
    "countryName": "United Arab Emirates",
    "countries": ["AE", "SA"],
    "workplaceType": "hybrid",
    "timeType": "Full time",
    "postedAt": "2026-10-16",
    "postedOnText": "Posted Yesterday",
    "jobReqId": "JR1000001",
    "jobUrl": "https://example.wd5.myworkdayjobs.com/External/job/United-Arab-Emirates-Dubai/Solutions-Architect---AI--Middle-East_JR1000001",
    "applyUrl": "https://example.wd5.myworkdayjobs.com/External/job/United-Arab-Emirates-Dubai/Solutions-Architect---AI--Middle-East_JR1000001/apply",
    "description": "Help customers in the Gulf deploy AI.\nDesign architectures\n…",
    "hasDetails": true,
    "scrapedAt": "2026-10-18T09:00:00.000Z",
    "changeType": "new",
    "changedFields": [],
    "firstSeenAt": "2026-10-18T09:00:00.000Z",
    "lastSeenAt": "2026-10-18T09:00:00.000Z",
    "closedAt": null
}
```

`RUN_SUMMARY` (default key-value store) lists every site with its status and error, jobs on the site, jobs listed, whether the listing was complete, whether the country filter ran on the site or locally, and matching, saved, new, updated, and closed counts by country.

### Use it from code, n8n, Make, or an AI agent

```bash
curl -X POST "https://api.apify.com/v2/acts/pharaoh_data~workday-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"careerSiteUrls":["https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"],"countries":["DE"],"outputMode":"changes","monitorId":"nvidia-de"}'
```

```python
import os

from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("pharaoh_data/workday-jobs-scraper").call(run_input={
    "careerSiteUrls": ["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"],
    "countries": ["AE", "SA"],
    "outputMode": "changes",
})
new_jobs = [job for job in client.dataset(run["defaultDatasetId"]).iterate_items() if job["changeType"] == "new"]
```

- **Alerts:** schedule a task, then add a webhook or the Slack, email, or Google Sheets integration on "Run succeeded".
- **AI agents (MCP):** `https://mcp.apify.com/?actors=pharaoh_data/workday-jobs-scraper`

### Limits and good to know

- **Workday returns at most 2,000 jobs per search.** For bigger employers, narrow with **Countries** or **Search text**. `maxJobsPerSite` caps listing at 2,000.
- **Descriptions** need one request per job. In "All current jobs" mode with descriptions on, the first run of a large site takes a few minutes at the default 2 requests per second. "Changes only" mode keeps later runs short.
- **Supported hosts:** `*.myworkdayjobs.com` and `wd*.myworkdaysite.com`. Custom career domains that embed Workday aren't supported; use the underlying Workday URL.
- The Actor uses the public JSON endpoints that Workday career pages themselves load. They aren't a documented API and can change. Per-site errors are reported in `RUN_SUMMARY`, and other sites still run.
- Use the data in line with each employer's site terms and applicable law. Descriptions are employer content; contact details in them are redacted by default.

### Pricing

Pay per event: you pay per **saved job record** (including closed-job records), plus Apify's small Actor start event. If the Pricing tab lists a **Job change** event, records saved in "Changes only" mode are billed at that price. See the **Pricing** tab for current amounts.

### FAQ

**How do I find a company's Workday URL?**
Open its careers page and click any job. If the address contains `myworkdayjobs.com`, copy everything up to the site name (for example `https://company.wd5.myworkdayjobs.com/External`). A job link also works.

**Why did a site fail with HTTP 422?**
The site name in the URL is wrong. Workday site names are case-sensitive; copy the URL straight from the careers page.

**Why are some countries empty?**
Without detail pages, a listing that says "3 Locations" has no readable country. Keep **Include job descriptions** on, or use the **Countries** filter, which is applied on the site.

# Actor input Schema

## `careerSiteUrls` (type: `array`):

Career-site addresses on myworkdayjobs.com or myworkdaysite.com, such as https://company.wd5.myworkdayjobs.com/External (a job link from the site also works). Up to 50 sites. Only use sites whose terms permit your use; robots.txt is always respected.

## `searchText` (type: `string`):

Optional search sent to each career site, like typing in its search box (for example "data engineer").

## `countries` (type: `array`):

Keep jobs in these countries. Use names or ISO codes, such as Germany, AE, "Saudi Arabia", US. When the site offers a country filter it is applied on the site, so fewer requests are needed. Leave empty for all countries.

## `jobTitles` (type: `array`):

Optional phrases to match in job titles. Any phrase can match.

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

Optional city or region terms to match in job locations, such as Munich, Dubai, or Remote.

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

Optional terms to match in the title, description, or location. Requires reading each job's detail page.

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

Keep jobs posted within this many days. 0 disables the filter.

## `maxJobsPerSite` (type: `integer`):

How many listings to read from each site (Workday returns at most 2,000 per search; use search text or countries to narrow large sites).

## `maxResults` (type: `integer`):

Maximum job records saved per run, including closed-job records. Each record is one billable result.

## `includeDescriptions` (type: `boolean`):

Read each saved job's detail page for the full description, exact locations, country, start date, and requisition ID. In "Changes only" mode only new and updated jobs are read, which keeps scheduled runs fast.

## `trackChanges` (type: `boolean`):

Label each job new, updated, or unchanged compared with the previous run, and report removed jobs as closed. History is kept in your account's named key-value store workday-jobs-scraper-state.

## `outputMode` (type: `string`):

"All current jobs" saves every matching job. "Changes only" saves new, updated, and closed jobs, for alerts and cheaper scheduled runs.

## `includeClosed` (type: `boolean`):

Save a record with changeType "closed" when a previously saved job disappears from a site whose full listing was read.

## `monitorId` (type: `string`):

Optional name for this monitor's history, such as "nvidia-uae". When empty, it is derived from the sites, search text, and countries.

## `redactContactDetails` (type: `boolean`):

Remove email addresses, phone numbers, and personal LinkedIn links from descriptions.

## `maxRequestsPerSecond` (type: `integer`):

Politeness limit for each career site (1–4).

## `maxConcurrency` (type: `integer`):

How many different career sites to read at once (1–5).

## Actor input object example

```json
{
  "careerSiteUrls": [
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "searchText": "",
  "countries": [
    "United Arab Emirates",
    "Saudi Arabia",
    "Germany"
  ],
  "jobTitles": [],
  "locations": [],
  "keywords": [],
  "postedWithinDays": 0,
  "maxJobsPerSite": 500,
  "maxResults": 5000,
  "includeDescriptions": true,
  "trackChanges": true,
  "outputMode": "all",
  "includeClosed": true,
  "monitorId": "",
  "redactContactDetails": true,
  "maxRequestsPerSecond": 2,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

Dataset of job records with change status.

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

Per-site totals: listed, matching, saved, new, updated, closed, and jobs by country.

# 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 = {
    "careerSiteUrls": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "countries": [
        "United Arab Emirates",
        "Saudi Arabia",
        "Germany"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pharaoh_data/workday-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 = {
    "careerSiteUrls": ["https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"],
    "countries": [
        "United Arab Emirates",
        "Saudi Arabia",
        "Germany",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("pharaoh_data/workday-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 '{
  "careerSiteUrls": [
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "countries": [
    "United Arab Emirates",
    "Saudi Arabia",
    "Germany"
  ]
}' |
apify call pharaoh_data/workday-jobs-scraper --silent --output-dataset

```

## MCP server setup

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