# Workday Scraper (`mlg14/workday-scraper`) Actor

Extract public Workday job listings from employer career sites, including titles, locations, posting dates, employment types, descriptions, and application links. Search across supplied sites and export results to CSV or JSON.

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

## Pricing

$1.00 / 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.

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 Scraper

Scrape public Workday job listings from employer career sites and export Workday jobs to CSV or JSON. This Workday API alternative collects titles, locations, posting dates, full descriptions, application links, and source employment details from the career sites you provide.

Each input URL identifies one public career site hosted on `myworkdayjobs.com`. Add several URLs to collect openings from several employers in one run. Search the supplied sites, apply inclusion and exclusion phrases, and set a result limit that fits a small review or a larger recurring export. The actor reads public listings and their public detail records; it does not require a candidate account.

### What data can you extract from Workday?

One dataset row represents one public job posting. Field names remain the same across sites, while the availability and wording of source fields vary by employer.

| Field | Description | Example |
| --- | --- | --- |
| `jobId` | Posting identifier returned by the career site | `f868e234c2da1000d4aae21a71660000` |
| `requisitionId` | Employer requisition reference | `JR-0110178` |
| `title` | Job title | `Software Development Engineer, SRE (US Federal)` |
| `jobUrl` | Public page for the posting and application | `https://workday.wd5.myworkdayjobs.com/Workday/job/...` |
| `companyName` | Employer name displayed in the career site's page metadata | `Workday` |
| `hiringOrganization` | Hiring organization label in the detail record | `Workday Government, LLC` |
| `location` | Location as published by the employer | `USA.VA.Reston` |
| `country` | Published country name | `United States of America` |
| `countryCode` | Two-letter country code when available | `US` |
| `remoteType` | Source remote arrangement label, when available | `Flex` |
| `employmentType` | Source time type or employment label | `Full Time` |
| `postedDate` | Posting start date | `2026-09-25` |
| `postedOn` | Relative date label shown on the site | `Posted Yesterday` |
| `applicationDeadline` | Published application end date, when available | `2026-10-31` |
| `canApply` | Whether the detail record says applications are open | `true` |
| `description` | Full job description as text or HTML | `Your work days are brighter here...` |
| `salaryText` | A published salary or pay-range line, when detected | `Primary Location Base Pay Range: $137,000 USD - $205,400 USD` |
| `careerSiteUrl` | Career site that supplied the posting | `https://workday.wd5.myworkdayjobs.com/Workday` |

`salaryText` preserves source wording rather than converting amounts to a single currency or period. A listing may describe several ranges for different locations or grades, so a single line cannot replace the full compensation section in `description`. For pay analysis, inspect the full description and the original posting before comparing numbers. `remoteType` is likewise the employer's label: a value such as `Flex` should be read with that employer's own policy, not treated as a universal remote-work category.

### How to scrape Workday

1. Open a public employer career site on `myworkdayjobs.com` and copy its URL. A URL ending in the site's name works; a URL for an individual job on the same site also works.
2. Paste one or more URLs into **Career site URLs**. Each URL identifies a separate career site. The actor does not need a login or a list of individual job links.
3. Optionally add **Search text** and title, location, or description phrases. Set **Maximum jobs in total** and, when using several sites, **Maximum jobs per site**.
4. Run the actor. Open its dataset to inspect the job rows, then download the dataset as JSON or CSV. Use the direct `jobUrl` to verify any opening before acting on it.

The search is scoped to the career sites in your input. It does not search every organization hosted on Workday automatically. If your goal is to follow a particular employer, use that employer's public career-site URL. If an employer has separate sites for regions or business units, add each public site that matters to you.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `careerSiteUrls` | string array | Required | One or more public Workday career-site URLs. |
| `searchText` | string | Empty | Text passed to the site's own job search. |
| `titleIncludes` | string array | Empty | Keep titles containing any phrase. |
| `titleExcludes` | string array | Empty | Drop titles containing any phrase. |
| `locationIncludes` | string array | Empty | Keep displayed locations containing any phrase. |
| `locationExcludes` | string array | Empty | Drop displayed locations containing any phrase. |
| `descriptionIncludes` | string array | Empty | Keep descriptions containing any phrase. |
| `descriptionExcludes` | string array | Empty | Drop descriptions containing any phrase. |
| `descriptionType` | `text` or `html` | `text` | Choose the format of `description`. |
| `maxItems` | integer | `100` | Maximum dataset rows across all sites; `0` removes this limit. |
| `maxJobsPerSite` | integer | `0` | Maximum rows from each site; `0` removes this limit. |
| `proxyConfiguration` | object | Platform proxy | Optional proxy override. |

For example, this input requests up to 40 public jobs from one site, with the full descriptions converted to readable text:

```json
{
  "careerSiteUrls": ["https://workday.wd5.myworkdayjobs.com/Workday"],
  "maxItems": 40,
  "descriptionType": "text"
}
```

The inclusion arrays use **any** matching phrase within each field. If `titleIncludes` contains `engineer` and `architect`, a title containing either word passes. An exclusion match removes the row. Comparisons ignore case and use the wording as displayed by the career site; they do not translate names, expand abbreviations, or infer related job families. An empty array imposes no filter.

`searchText` is handled by the site's search endpoint and can reduce the amount of paging needed. The phrase filters are applied by this actor to the returned results. Title and location filters are checked before loading a full job detail. Description filters are checked after the detail is read. If you request a narrow description phrase from a large site, expect more source requests per delivered row.

### Output example

This shortened row comes from a successful run on 26 September 2026. The real `description` field contains the full published text; it is shortened here for readability.

```json
{
  "jobId": "f868e234c2da1000d4aae21a71660000",
  "requisitionId": "JR-0110178",
  "title": "Software Development Engineer, SRE (US Federal)",
  "jobUrl": "https://workday.wd5.myworkdayjobs.com/Workday/job/USAVAReston/Software-Development-Engineer--SRE--US-Federal-_JR-0110178",
  "companyName": "Workday",
  "hiringOrganization": "Workday Government, LLC",
  "location": "USA.VA.Reston",
  "country": "United States of America",
  "countryCode": "US",
  "remoteType": "Flex",
  "employmentType": "Full Time",
  "postedDate": "2026-09-25",
  "postedOn": "Posted Yesterday",
  "applicationDeadline": "2026-10-31",
  "canApply": true,
  "description": "Your work days are brighter here.\nWe're obsessed with making hard work pay off...",
  "salaryText": "Primary Location Base Pay Range:  $137,000 USD - $205,400 USD",
  "careerSiteUrl": "https://workday.wd5.myworkdayjobs.com/Workday"
}
```

The direct URL is the practical record key for downstream exports. A requisition reference may appear in several postings or locations, and a job title can be reused. If you combine several scheduled runs, deduplicate on `jobUrl` when you want one row per public posting. If you instead want to group regional copies of a role, group by employer and requisition ID after reviewing the source records.

### Use cases

- **Recruiting teams:** monitor selected employers' public openings and keep a dated record of new titles, work arrangements, and hiring locations.
- **Job seekers:** assemble a focused list of roles from career sites they trust, then open the original `jobUrl` to confirm requirements and apply.
- **Market researchers:** compare advertised skills, job families, and geographic hiring patterns across a known list of employers.
- **Compensation researchers:** find postings that publish a salary line, while retaining the full description for context and location-specific ranges.
- **Operations teams:** build a recurring dataset for change detection using posting URLs and dates rather than copying job pages by hand.
- **Publishers:** create a reviewed feed of current public openings, with links that point readers back to each employer's application page.

The actor works best when the set of employers is known. It is particularly useful when each employer publishes many jobs and checking every page manually would be slow. It can also handle small sites; the row cap only matters on very large job catalogs.

### How much does it cost to scrape Workday?

The result charge is **$0.001 per delivered job**, or **$1 per 1,000 results**. The charge follows rows exported to the dataset. A source search that finds no matching postings does not create result rows. Your input limits therefore control the maximum number of paid results from a run.

| Delivered jobs | Result charge |
| ---: | ---: |
| 100 | $0.10 |
| 1,000 | $1.00 |
| 5,000 | $5.00 |

For a 40-job review like the verified example above, the result charge is $0.04. A recurring job monitor capped at 100 results per run would charge at most $0.10 in result events for each run. Platform usage is handled within the actor's result pricing. The amount of work needed to find those results can vary with the number of sites and the selectivity of your filters, but the row limit remains the direct way to cap delivered results.

### Tips for best results

Start with the exact public career-site URL. URLs for an individual job on a site are accepted, but the actor scans that site's listings; it does not restrict output to the single job in the URL. If you want to monitor several distinct employers, add each site URL separately. A broad URL without a career-site path cannot identify which site to search.

Use `searchText` when a site's catalog is large and a particular skill or role family is the focus. Then use title or location phrases to trim the results. The actor sends `searchText` to the site's public job search; the other phrase filters apply to the returned listings. For example, a title inclusion of `engineer` is broader than a single exact title and can collect several related titles. Add exclusions if some recurring title wording is out of scope.

When filtering by location, inspect the site's displayed format first. A location may appear as a city and region, a country, or a code-like label such as `USA.VA.Reston`. The filter matches text as it appears; a phrase like `Virginia` will not match a source listing that only says `VA`. If the same role appears in several locations, expect separate postings when the career site exposes separate URLs.

Set `maxItems` for a global cap and `maxJobsPerSite` if one large employer should not consume the entire result allowance. The actor visits sites in input order. For a balanced multi-site sample, set a per-site cap and a total cap high enough to include each site. For a full export, set both caps to `0`, then monitor run duration and output volume.

Choose `descriptionType: "text"` for analysis, reading, and simple phrase searches. Choose `html` when preserving headings, lists, and links from the published description matters. Description inclusion and exclusion phrases work with either choice because the actor checks the corresponding description value after loading the detail. The plain-text conversion may change whitespace while preserving the wording.

### Limits

This actor reads **public** employer career sites hosted on `myworkdayjobs.com`. It does not access candidate profiles, application forms behind a login, or private job feeds. You supply the employer sites; there is no built-in directory of all Workday tenants and no guarantee that every employer using Workday exposes the same career site structure.

The public listings endpoint returned 20 jobs per page in the tested sites. One tested high-volume site reported a 2,000-job total, and a request beyond that offset returned the first page again. The actor avoids that loop and splits large result sets by public facets such as job family and location when those facets are available. If a very large slice has no further useful facets, the actor logs that the public listing cap may leave jobs out. Search terms and narrower employer sites are practical ways to reduce that risk.

Fields vary by posting. `remoteType`, `applicationDeadline`, `salaryText`, and some organization or location details can be empty. A missing `salaryText` means no suitable source line was detected; it is not proof that compensation is absent from the posting. Salary lines can contain multiple locations, pay grades, or currencies, and the actor does not turn them into a single numeric estimate. Job content and availability can change between the listing page and the detail request. A removed posting may be skipped rather than exported with partial data.

Search results also depend on the site's own matching and ordering. The actor does not promise a particular ranking, a fixed crawl time, or a historical archive of expired jobs. The `postedDate` comes from the job detail; `postedOn` is a relative label that can become stale after export. For monitoring, record the run time alongside the dataset and compare `jobUrl` values between runs.

### Use with automated clients (MCP)

The actor's input and output schemas can be used by an automated client to request a bounded export and inspect stable field names. Two useful requests are:

> Collect up to 100 public engineering jobs from this Workday career site. Return title, location, posted date, and job URL, and keep the full description in the dataset.

> Check these three Workday career sites for titles containing analyst. Exclude postings whose location contains a region I specify, cap each site at 50 jobs, and give me the dataset link.

Supply the actual public career-site URLs with those requests. Automated clients should treat the source fields as published claims, especially location, remote policy, and pay. The original `jobUrl` remains the right place to verify current details before an application or publication.

### FAQ

**Is scraping these jobs legal?** The actor reads publicly accessible job postings. Rules differ by jurisdiction and use case. Review the site's terms and applicable privacy and data-protection requirements, and avoid using the output to collect or misuse personal information. Keep links and attribution to the original postings where appropriate.

**Do I need to configure a proxy?** Usually no. The default input uses the platform proxy and starts with a lower-cost route. If a site blocks requests, the shared fetch layer can rotate its session and escalate its proxy route. A particular employer may still change access rules or become unavailable.

**How fast is a run?** A verified 40-job run completed successfully in under a minute on the remote platform. Larger runs take longer because each delivered job requires a detail request and a broad catalog requires listing pages. Network response time, source limits, filters, and the number of supplied sites all affect duration.

**Can I schedule and monitor runs?** Yes. Save an input configuration, run it on a schedule, and compare the resulting datasets. Use the URL field to identify postings that were newly seen, still present, or absent from the latest export. A missing row can also be caused by filters or a temporary source issue, so confirm removals before treating them as closed roles.

**Can I export to a spreadsheet?** Yes. Download the dataset as CSV for spreadsheet analysis or use JSON for systems that need structured fields. The description can be long, so a spreadsheet view may be easier to scan if you hide or move that column while keeping it in the export.

**Why is a field empty?** Employers choose what to publish, and their career-site configurations differ. A deadline or remote label may be unavailable for a particular posting. Compensation often appears only in description text. Check the original job page when a field matters to a decision.

**Does a job URL input scrape only that job?** No. A job URL identifies its parent career site. The actor searches and pages through that site's public listings, then loads details for the jobs that pass the filters. Use a restrictive title or search phrase if you want a small related set.

### Integrations

Use the dataset endpoint to pull JSON or CSV into your own application, a webhook-driven workflow, a spreadsheet, or a recurring reporting process. Scheduled runs can feed a job monitor, and the stable `jobUrl` field supports deduplication between runs. Keep the source URL with each record so downstream users can open the current posting directly.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request.

# Actor input Schema

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

Public myworkdayjobs.com career site URLs. Add one URL per employer site; a job URL from the site is also accepted.

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

Optional text sent to each career site's job search. Leave empty for all public jobs.

## `titleIncludes` (type: `array`):

Keep jobs whose title contains any supplied phrase, ignoring case. Empty means all titles.

## `titleExcludes` (type: `array`):

Remove jobs whose title contains any supplied phrase, ignoring case.

## `locationIncludes` (type: `array`):

Keep jobs whose displayed location contains any supplied phrase, ignoring case.

## `locationExcludes` (type: `array`):

Remove jobs whose displayed location contains any supplied phrase, ignoring case.

## `descriptionIncludes` (type: `array`):

Keep jobs whose full description contains any supplied phrase. Filtering happens after job details are fetched.

## `descriptionExcludes` (type: `array`):

Remove jobs whose full description contains any supplied phrase.

## `descriptionType` (type: `string`):

Export the full job description as plain text or source HTML.

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

Stop after this many jobs across all career sites. 0 means no total cap.

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

Stop after this many jobs from each career site. 0 means no per-site cap.

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

Apify Proxy is used automatically. Override only when needed.

## Actor input object example

```json
{
  "careerSiteUrls": [
    "https://workday.wd5.myworkdayjobs.com/Workday"
  ],
  "searchText": "",
  "descriptionType": "text",
  "maxItems": 100,
  "maxJobsPerSite": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Public job postings in the default dataset.

# 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://workday.wd5.myworkdayjobs.com/Workday"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/workday-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://workday.wd5.myworkdayjobs.com/Workday"] }

# Run the Actor and wait for it to finish
run = client.actor("mlg14/workday-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://workday.wd5.myworkdayjobs.com/Workday"
  ]
}' |
apify call mlg14/workday-scraper --silent --output-dataset

```

## MCP server setup

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