# StepStone Group Jobs Scraper — Totaljobs, IrishJobs & more (`memo23/stepstone-group-scraper`) Actor

Scrape jobs across the whole StepStone Group in one run — Totaljobs, CWJobs, Jobsite, Caterer, IrishJobs, StepStone and sister brands — via the two shared StepStone Group backends. Unified JobPosting output with a per-brand column.

- **URL**: https://apify.com/memo23/stepstone-group-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Jobs, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 job scrapeds

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## StepStone Group Jobs Scraper — Totaljobs, CWJobs, Caterer, IrishJobs, StepStone DE/AT/BE/NL

Scrape job postings across the **entire StepStone Group in a single run** — Totaljobs, CWJobs, Jobsite and Caterer in the UK, IrishJobs in Ireland, and StepStone Germany, Austria, Belgium and the Netherlands — and get one clean, unified dataset back.

Pick the portals you want, type a keyword and a location, and every selected brand is searched at once. No juggling four different scrapers, four output shapes, or four billing lines.

![StepStone Group Jobs Scraper](https://muhamed-didovic.github.io/assets/stepstone-group-hero.png)

---

### Why Use This Scraper?

- **One run, the whole Group.** Nine portals across the UK, Ireland, Germany, Austria, Belgium and the Netherlands — searched together, returned in one dataset.
- **One unified schema.** Every row has the same fields regardless of which brand it came from, plus a `brand` and `sourceSite` column so you always know the source.
- **Keyword + location, no URL building.** Multi-select the brands, type "chef" and "London", and go. Or paste raw brand URLs if you prefer.
- **Structured salary bands.** Min / max / currency / period parsed out wherever the employer disclosed a figure — including correct handling of continental European number formats.
- **Employer firmographics.** Company name, logo, internal company page and (where available) a company ID on every row.
- **Geo-coordinates.** Latitude/longitude on UK rows for mapping and territory analysis.
- **Built for scale.** Efficient JSON APIs under the hood — not fragile HTML scraping — with automatic pagination and per-brand result caps.

---

### Overview

The StepStone Group Jobs Scraper is for recruiters, sourcers, market-intelligence teams, and data teams who need job-market data spanning multiple StepStone Group brands at once.

It returns a flat, one-row-per-job dataset. Each row is a single job posting normalized to a shared **JobPosting** shape: identity (job ID, URL, title), dates, employer, location, structured salary, employment type and apply flow. A `brand` column tags every row with its source portal (`totaljobs`, `caterer`, `irishjobs`, `stepstone-de`, …), so you can filter, group, or split by brand downstream.

Data comes from two shared StepStone Group backends:

- The **Totaljobs-Group** brands (Totaljobs, CWJobs, Jobsite, Caterer) share one mobile API.
- The **StepStone unified platform** brands (IrishJobs, StepStone DE/AT/BE/NL) share the unified-resultlist API.

You don't need to know or care which is which — the actor routes each selected brand automatically.

---

### Supported Inputs

You can drive the actor two ways — use either, or mix both in one run.

#### 1. Brands + keyword + location (recommended)

Select one or more portals in the **StepStone Group portals** multi-select, then set a keyword and/or location. Every selected brand is searched.

Supported brands:

| Brand id | Portal | Market |
|---|---|---|
| `totaljobs` | Totaljobs | UK |
| `cwjobs` | CWJobs | UK (tech) |
| `jobsite` | Jobsite | UK |
| `caterer` | Caterer.com | UK (hospitality) |
| `irishjobs` | IrishJobs | Ireland |
| `stepstone-de` | StepStone | Germany |
| `stepstone-at` | StepStone | Austria |
| `stepstone-be` | StepStone | Belgium |
| `stepstone-nl` | StepStone | Netherlands |

#### 2. Start URLs

Paste raw listing or job-detail URLs from any supported brand — they are auto-routed to the correct backend by host. Mixing brands in one list is fine.

```json
{
  "startUrls": [
    "https://www.totaljobs.com/jobs/software-engineer/in-london",
    "https://www.caterer.com/jobs/chef",
    "https://www.irishjobs.ie/jobs/nurse/in-dublin"
  ]
}
````

Listing URLs auto-paginate until your `maxItems` budget is reached. Direct job-detail URLs emit one row each.

#### Not supported

- Sites outside the StepStone Group (any host not in the table above is skipped with a log note).
- Pasted **StepStone DE/AT/BE/NL job-detail** URLs (their detail URL format differs) — use the brand + keyword search for those markets instead. UK and Irish detail URLs are fully supported.
- Login-gated content, candidate CVs, or recruiter-only data.

***

### Use Cases

| Audience | What they get |
|---|---|
| Recruitment agencies | Cross-brand vacancy feeds for one keyword across UK/IE/DACH/BENELUX in a single pull |
| Talent sourcing | Employer + role lists filtered by location and posted date |
| Market intelligence | Volume, salary bands and hiring-company trends per brand and per country |
| Job boards / aggregators | A normalized multi-source jobs feed under one schema |
| Salary benchmarking | Structured min/max/currency/period bands grouped by title and market |
| Lead generation | Hiring companies (with logos and internal profiles) actively posting roles |

***

### How It Works

![How the StepStone Group Jobs Scraper works](https://muhamed-didovic.github.io/assets/stepstone-group-how-it-works.png)

1. **You pick brands + a keyword/location** (or paste brand URLs). The actor builds the right search URL for each selected portal.
2. **Each brand is routed to its shared backend** — the Totaljobs-Group mobile API or the StepStone unified-resultlist API — automatically, by host.
3. **Listings are paginated via JSON APIs**, collecting job items up to your per-brand `maxItems` cap.
4. **Each job's detail page is fetched and parsed** into the unified JobPosting row, merging the listing item's structured salary, coordinates and skills.
5. **Rows are streamed to the dataset** as they're ready, each tagged with its `brand` and `sourceSite`.

***

### Input Configuration

| Field | Type | Description |
|---|---|---|
| `brands` | array | StepStone Group portals to scrape (multi-select). Each selected brand is searched with the keyword & location below. |
| `searchKeyword` | string | Job title / keyword to search across every selected brand (e.g. `software engineer`, `nurse`, `chef`). Optional. |
| `searchLocation` | string | Location to search across every selected brand (e.g. `London`, `Dublin`, `Berlin`). Optional — blank searches the whole country per brand. |
| `startUrls` | array | Raw listing or job-detail URLs from any supported brand. Auto-routed by host. Optional. |
| `maxItems` | integer | Max job rows per (brand × listing URL). Default 100. Direct detail URLs always emit 1 row each. |
| `maxConcurrency` | integer | Parallel HTTP requests for detail fetches. Default 4. |
| `maxRequestRetries` | integer | Per-URL retry budget on transient errors. Default 6. |
| `proxy` | object | Advanced override. By default each brand uses its proven proxy automatically. |

#### Example: three brands, one keyword

```json
{
  "brands": ["totaljobs", "caterer", "irishjobs"],
  "searchKeyword": "chef",
  "searchLocation": "London",
  "maxItems": 200
}
```

#### Example: continental StepStone markets

```json
{
  "brands": ["stepstone-de", "stepstone-at", "stepstone-be"],
  "searchKeyword": "engineer",
  "maxItems": 100
}
```

#### Example: paste URLs directly

```json
{
  "startUrls": [
    "https://www.totaljobs.com/jobs/in-manchester",
    "https://www.cwjobs.co.uk/jobs/devops"
  ],
  "maxItems": 50
}
```

***

### Output Overview

The dataset is flat: **one row per job posting**. Each row is normalized to the same JobPosting shape no matter which brand produced it. Provenance columns (`brand`, `backend`, `sourceSite`, `sourceSearchUrl`) let you trace every row back to its portal and the search that found it. Optional fields (structured salary, skills, coordinates, company ID) are populated when the source exposes them and are otherwise `null`.

***

### Output Samples

**From `brands: ["caterer"]`, keyword `chef` (Totaljobs-Group backend):**

```json
{
  "rowType": "job",
  "brand": "caterer",
  "backend": "naps",
  "sourceSite": "caterer.com",
  "sourceSearchUrl": "https://www.caterer.com/jobs/chef",
  "jobId": "107604788",
  "jobUrl": "https://www.caterer.com/job/chef/abbeywood-estate-job107604788",
  "title": "Chef",
  "employmentType": "FULL_TIME",
  "employer": {
    "name": "Abbeywood Estate",
    "url": "https://www.caterer.com/jobs/abbeywood-estate?cmpId=1460325",
    "logoUrl": "https://www.caterer.com/CompanyLogos/1460325.png",
    "id": 1460325
  },
  "location": {
    "text": "Northwich, Cheshire, CW8 2HW, GB",
    "locality": "Northwich",
    "region": "Cheshire",
    "postalCode": "CW8 2HW",
    "country": "GB",
    "lat": 53.22709,
    "lng": -2.60343
  },
  "salary": { "rawText": "£17 per hour", "min": 17, "max": null, "currency": "GBP", "period": "hour" },
  "applyType": "internal",
  "scrapedAt": "2026-07-13T16:00:00.000Z"
}
```

**From `brands: ["stepstone-at"]`, keyword `manager` (StepStone unified backend):**

```json
{
  "rowType": "job",
  "brand": "stepstone-at",
  "backend": "unified",
  "sourceSite": "stepstone.at",
  "jobId": "992653",
  "title": "Area Sales Manager (m/w/d) Nutzfahrzeuge",
  "employer": { "name": "WALTER LEASING GmbH", "id": null, "logoUrl": "https://..." },
  "location": { "text": "Wiener Neudorf, AT", "country": "AT", "lat": null, "lng": null },
  "salary": { "rawText": "€ 50.000", "min": 50000, "max": null, "currency": "EUR", "period": null },
  "applyType": "internal"
}
```

***

### Key Output Fields

**Provenance**

- `brand` — source portal id (`totaljobs`, `caterer`, `irishjobs`, `stepstone-de`, …)
- `backend` — which shared backend served it (`naps` or `unified`)
- `sourceSite` — host the job lives on
- `sourceSearchUrl` — the listing/search that discovered the row (null for pasted detail URLs)

**Job identity**

- `jobId`, `jobUrl`, `title`

**Job details**

- `description`, `datePosted`, `validThrough`, `employmentType`, `industry`, `directApply`, `jobLocationType`, `applicantLocationRequirements`, `workType`, `contractType`, `workFromHome`, `skills`

**Employer**

- `employer.name`, `employer.url`, `employer.logoUrl`, `employer.id`

**Location**

- `location.text`, `location.locality`, `location.region`, `location.postalCode`, `location.country`, `location.lat`, `location.lng`

**Salary**

- `salary.rawText`, `salary.min`, `salary.max`, `salary.currency`, `salary.period`

**Apply flow**

- `applyUrl`, `applyType` (`internal` / `external` / `unknown`)

***

### FAQ

**Which brands can I scrape in one run?** Any combination of the nine listed: Totaljobs, CWJobs, Jobsite, Caterer, IrishJobs, and StepStone DE/AT/BE/NL. Select as many as you want.

**Do all brands return the same fields?** Yes — every row uses one unified schema. Some optional fields (structured company ID, skills, coordinates) are only present where a given brand exposes them; they're `null` otherwise.

**Does StepStone NL return many jobs?** The Netherlands portal has a small inventory (StepStone has wound it down), so expect low volumes there. It's included for completeness; the DE, AT and UK/IE portals carry the bulk of the roles.

**Can I paste a StepStone Germany job link?** For DE/AT/BE/NL, use the brand + keyword search rather than pasting individual job-detail URLs — those markets use a different detail-URL format. UK and Irish detail URLs work directly.

**How is salary handled?** Where the employer disclosed a figure, it's parsed into min/max/currency/period. Continental European "€ 50.000" formats are read correctly (50000, not 50). Undisclosed roles keep the raw text (e.g. "€ Not Disclosed") with null min/max.

**Does it scrape candidate data or recruiter-only content?** No — only publicly listed job postings.

**How does pagination and the item cap work?** `maxItems` is applied per brand per listing URL. Three brands with `maxItems: 100` yields up to 300 rows (100 each). Direct detail URLs always emit exactly one row.

***

### Support

Found a bug, a missing field, or a brand you'd like added? Open an issue on the actor's **Issues** tab and we'll take a look. We actively maintain this scraper and respond to reports.

***

### Additional Services

Need a tailored export, a scheduled cross-brand feed, additional StepStone Group portals, or enrichment (e.g. employer contact emails)? We build custom scraping and data pipelines — reach out via the Issues tab to discuss your requirements.

***

### Explore More Scrapers

Prefer a single-country scraper, or need deeper per-brand coverage? Explore our dedicated job-board actors:

- Totaljobs UK Scraper
- CWJobs Scraper
- Jobsite Scraper
- Caterer.com Scraper
- IrishJobs Scraper
- StepStone Scraper

Browse the full collection on our Apify Store profile.

***

### ⚠️ Disclaimer

This actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by** The Stepstone Group, Totaljobs Group Ltd, or any of their subsidiaries or brands (Totaljobs, CWJobs, Jobsite, Caterer.com, IrishJobs, StepStone). All product names, logos, and brands are the property of their respective owners and are used for identification purposes only.

This scraper collects **only publicly available job-posting data** — the same information any visitor can see without logging in. It does not access private, gated, or personal candidate data. Users are responsible for ensuring their use of the scraped data complies with the source sites' Terms of Service, applicable data-protection laws (including GDPR and CCPA), and any other relevant regulations. Use the data lawfully and responsibly.

***

### SEO Keywords

StepStone scraper, StepStone Group scraper, Totaljobs scraper, CWJobs scraper, Jobsite scraper, Caterer.com scraper, IrishJobs scraper, StepStone Germany scraper, job posting scraper, job board scraper, jobs data extraction, recruitment data scraper, vacancy scraper, salary data scraper, hiring companies scraper, UK jobs scraper, Ireland jobs scraper, DACH jobs scraper, employer data extraction, job market intelligence, multi-brand jobs scraper, StepStone Austria scraper, StepStone Belgium scraper, StepStone Netherlands scraper

# Actor input Schema

## `brands` (type: `array`):

Which Group portals to include. Each selected brand is searched with the keyword & location below. Leave empty if you're only pasting Start URLs.

## `searchKeyword` (type: `string`):

Job title / keyword to search across every selected brand, e.g. `software engineer`, `nurse`, `chef`. Leave blank to browse everything in the location.

## `searchLocation` (type: `string`):

Town / city / region to search across every selected brand, e.g. `London`, `Dublin`, `Berlin`. Leave blank to search the whole country for each brand.

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

Raw listing URLs (e.g. `https://www.totaljobs.com/jobs/in-london`) or direct job-detail URLs from any supported brand. Auto-routed to the right backend by host; mixed brands in one run are fine. Overrides the keyword/location search for brands they belong to.

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

Maximum job rows per (brand × listing URL). 3 brands × maxItems 100 → up to 300 rows. Direct detail URLs always emit 1 row each. Free-tier users are capped at 100 rows total across the run.

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

Parallel HTTP requests for detail-page fetches. 3-5 is the sweet spot.

## `maxRequestRetries` (type: `integer`):

Per-URL retry budget on network errors, proxy failures, and transient blocks. Each retry rotates the proxy session. Default 6.

## `proxy` (type: `object`):

Optional override. By default each brand uses its proven proxy: Apify Residential GB for the Totaljobs-Group brands (their detail pages are Akamai-locked) and residential rotation for the StepStone unified-platform brands. Only set this if you know what you're doing.

## Actor input object example

```json
{
  "brands": [
    "totaljobs",
    "caterer",
    "irishjobs"
  ],
  "maxItems": 100,
  "maxConcurrency": 4,
  "maxRequestRetries": 6
}
```

# 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 = {
    "brands": [
        "totaljobs",
        "caterer",
        "irishjobs"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/stepstone-group-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 = { "brands": [
        "totaljobs",
        "caterer",
        "irishjobs",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/stepstone-group-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "brands": [
    "totaljobs",
    "caterer",
    "irishjobs"
  ]
}' |
apify call memo23/stepstone-group-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/stepstone-group-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "StepStone Group Jobs Scraper — Totaljobs, IrishJobs & more",
        "description": "Scrape jobs across the whole StepStone Group in one run — Totaljobs, CWJobs, Jobsite, Caterer, IrishJobs, StepStone and sister brands — via the two shared StepStone Group backends. Unified JobPosting output with a per-brand column.",
        "version": "0.0",
        "x-build-id": "3lzvmJ0CeOhEiOqR2"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~stepstone-group-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-stepstone-group-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~stepstone-group-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-stepstone-group-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~stepstone-group-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-stepstone-group-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "brands": {
                        "title": "StepStone Group portals to scrape",
                        "type": "array",
                        "description": "Which Group portals to include. Each selected brand is searched with the keyword & location below. Leave empty if you're only pasting Start URLs.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "totaljobs",
                                "cwjobs",
                                "jobsite",
                                "caterer",
                                "irishjobs",
                                "stepstone-de",
                                "stepstone-at",
                                "stepstone-be",
                                "stepstone-nl"
                            ],
                            "enumTitles": [
                                "Totaljobs (UK)",
                                "CWJobs (UK, tech)",
                                "Jobsite (UK)",
                                "Caterer.com (UK hospitality)",
                                "IrishJobs (IE)",
                                "StepStone (DE)",
                                "StepStone (AT)",
                                "StepStone (BE)",
                                "StepStone (NL)"
                            ]
                        }
                    },
                    "searchKeyword": {
                        "title": "Search keyword",
                        "type": "string",
                        "description": "Job title / keyword to search across every selected brand, e.g. `software engineer`, `nurse`, `chef`. Leave blank to browse everything in the location."
                    },
                    "searchLocation": {
                        "title": "Location",
                        "type": "string",
                        "description": "Town / city / region to search across every selected brand, e.g. `London`, `Dublin`, `Berlin`. Leave blank to search the whole country for each brand."
                    },
                    "startUrls": {
                        "title": "Start URLs (optional)",
                        "type": "array",
                        "description": "Raw listing URLs (e.g. `https://www.totaljobs.com/jobs/in-london`) or direct job-detail URLs from any supported brand. Auto-routed to the right backend by host; mixed brands in one run are fine. Overrides the keyword/location search for brands they belong to.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max jobs per brand listing",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum job rows per (brand × listing URL). 3 brands × maxItems 100 → up to 300 rows. Direct detail URLs always emit 1 row each. Free-tier users are capped at 100 rows total across the run.",
                        "default": 100
                    },
                    "maxConcurrency": {
                        "title": "Max parallel requests",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Parallel HTTP requests for detail-page fetches. 3-5 is the sweet spot.",
                        "default": 4
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Per-URL retry budget on network errors, proxy failures, and transient blocks. Each retry rotates the proxy session. Default 6.",
                        "default": 6
                    },
                    "proxy": {
                        "title": "Proxy configuration (advanced override)",
                        "type": "object",
                        "description": "Optional override. By default each brand uses its proven proxy: Apify Residential GB for the Totaljobs-Group brands (their detail pages are Akamai-locked) and residential rotation for the StepStone unified-platform brands. Only set this if you know what you're doing."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
