# Manpower Scraper — Multi-Country Staffing Agency Jobs (`studio-amba/manpower-scraper`) Actor

Scrape job listings from Manpower across Germany, Belgium (Dutch and French) and the Netherlands — one of the world's largest staffing agencies. No login or cookies required.

- **URL**: https://apify.com/studio-amba/manpower-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Manpower Scraper — Multi-Country

Extract job listings from [Manpower](https://www.manpower.de), one of the world's largest staffing agencies, as clean structured JSON — across Germany, Belgium (Dutch and French) and the Netherlands from a single actor. Pick a country, search by keyword, and get job titles, locations, employment type, salary and posting dates.

No login. No cookies. No browser automation. The actor talks to Manpower's own job-search backends directly.

### What this actor does

Manpower does not run one shared platform across every market. This actor
handles both platforms it actually uses in these four markets:

- **Germany and the Netherlands** run the same Sitecore JSS template with a
  clean JSON search API behind it. The actor calls that API directly.
- **Belgium** (Dutch and French) runs a completely different, server-rendered
  platform. The actor requests the search-results pages directly and parses
  the listings out of the HTML — no browser needed.

Either way you get one row per job with:

- Job title
- Location
- Employment type and salary (Germany/Netherlands only — see Limitations)
- Industry/category
- Posting date
- A plain-text description excerpt
- Manpower's own link to the job

### Supported countries

| Input value | Market |
|---|---|
| `DE` | Germany — default |
| `BE-nl` | Belgium (Dutch) |
| `BE-fr` | Belgium (French) |
| `NL` | Netherlands |

France was tested and excluded: `manpower.fr` returns HTTP 403 on a plain
request — a different WAF from the other three properties — so it can't be
covered without a much heavier anti-bot approach. All four markets above
were verified live against real, current listings before shipping.

### Why use it

- **Pan-European staffing market research** — track what roles Manpower is
  placing across four markets from one tool instead of four.
- **Recruitment and sourcing** — build a live feed of temp and permanent
  positions for a role, industry or region.
- **Salary benchmarking** — most German and Dutch listings disclose an
  hourly pay rate.
- **Coverage alongside Randstad and Adecco** — the third leg of the "big
  three" pan-European staffing agencies, so a market-wide temp-staffing
  dataset only needs this actor plus its two siblings below.

### How to scrape Manpower data

1. Open the actor and pick a **Country** (e.g. `DE` for Germany).
2. Set a **Search Query** in the local language (e.g. `lager` for Germany,
   `magazijn` for Belgium/Netherlands, `entrepôt` for French Belgium).
   Leave it empty to get all current listings for the whole country.
3. Optionally set a **Location filter** to narrow results to a city.
4. Set **Max Results** and click **Start**.

For Germany/Netherlands, the actor pages through Manpower's own search API
in 10-result pages (the only page size proven to paginate correctly — see
Limitations) until it reaches your Max Results or runs out of listings. For
Belgium, it requests the search-results HTML page by page (20 results per
page) and parses each job card directly out of the markup.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `country` | string | Market to search. One of `DE`, `BE-nl`, `BE-fr`, `NL`. Default: `DE`. |
| `searchQuery` | string | Keyword in the local language. Empty = all current listings. |
| `location` | string | Optional city filter, applied client-side. |
| `maxResults` | integer | Maximum number of listings to return (max 500). Default: `50`. |
| `proxyConfiguration` | object | Apify proxy settings. Default: Apify's automatic proxy (no residential group needed). |

#### Example input

```json
{
    "country": "DE",
    "searchQuery": "lager",
    "location": "",
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
}
```

### Output

Each dataset item looks like this (Germany):

```json
{
    "title": "Lagerarbeiter (gn)",
    "company": "Manpower",
    "locationRaw": "Hoyerswerda",
    "locationParsed": { "city": "Hoyerswerda", "country": "Germany" },
    "language": "de",
    "postedAt": "2026-08-28T08:50:50Z",
    "descriptionSnippet": "Auf zum neuen Job mit Manpower! Starten Sie als Lagerarbeiter (gn) zum nächstmöglichen Zeitpunkt bei uns durch! ...",
    "url": "https://www.manpower.de/de/jobs/lagerarbeiter-gn-02977-hoyerswerda/6fdd1102-e666-4843-8f13-019af57aa8e8/",
    "employmentType": "Vollzeit",
    "salaryRaw": "€ 15 - € 16 pro Stunde",
    "industry": "Produktion und Herstellung",
    "source": "www.manpower.de",
    "scrapedAt": "2026-08-29T09:14:03.000Z",
    "jobId": "6fdd1102-e666-4843-8f13-019af57aa8e8"
}
```

And on Belgium, where employment type and salary aren't exposed in the
listing view (see Limitations):

```json
{
    "title": "Teamleader magazijn",
    "company": "Manpower",
    "locationRaw": "Willebroek",
    "locationParsed": { "city": "Willebroek", "country": "Belgium" },
    "language": "nl",
    "postedAt": "2026-08-05T09:14:39.673Z",
    "postedAtRaw": "Geplaatst 24 dagen geleden",
    "descriptionSnippet": "Beschrijving van de klant: TEAMLEADER MAGAZIJN | WILLEBROEK | 2 PLOEGEN MANPOWER Industry is specialist in het rekruteren van technisch geschoolde arbeiders en bedienden...",
    "url": "https://www.manpower.be/nl/vacature/teamleader-magazijn-281199",
    "source": "www.manpower.be/nl/vacatures",
    "scrapedAt": "2026-08-29T09:14:39.674Z",
    "jobId": "281199"
}
```

#### Output fields

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Job title, as posted |
| `company` | string | Always `Manpower` |
| `locationRaw` | string | Location as shown on the listing |
| `locationParsed` | object | `{ city, country }` |
| `language` | string | ISO 639-1 language code of the posting |
| `postedAt` | string | ISO 8601 posting timestamp. On Belgium this is best-effort computed from a relative date string ("24 days ago") — see `postedAtRaw`. |
| `postedAtRaw` | string | Original relative-date text (Belgium only) |
| `descriptionSnippet` | string | Plain-text excerpt of the job description |
| `url` | string | Manpower's own job link |
| `employmentType` | string | Employment type, e.g. `Vollzeit`. Not present on Belgium listings. |
| `salaryRaw` | string | Raw salary information, when disclosed. Not present on Belgium listings. |
| `industry` | string | Industry/category label or slug, when available |
| `source` | string | Source domain + path identifier |
| `scrapedAt` | string | ISO 8601 timestamp of collection |
| `jobId` | string | Unique Manpower job identifier |

### Cost estimate

Every result comes from a listing-page request only — there is no
per-result detail-page fetch. Germany/Netherlands requests 10 results per
page (the only page size proven to paginate correctly); Belgium requests
20 results per page. A 50-result run is 5 requests (Germany/Netherlands)
or 3 requests (Belgium), all lightweight — no browser rendering. Usage is
only charged after a run finishes with status SUCCEEDED — a failed or
aborted run doesn't bill for partial results.

### Limitations

- **France is not covered.** `manpower.fr` returns HTTP 403 on a plain
  request, verified live — a different WAF from the other three Manpower
  properties this actor covers.
- **Belgium listings don't include employment type or salary.** Those
  fields only exist on the per-job detail page on manpower.be, which this
  actor doesn't fetch (to keep every country at one request per page of
  results). `industry` is available on Belgium via the search page's
  category tag.
- **Belgium's `postedAt` is approximate.** The Belgium listing page only
  shows a relative string ("24 dagen geleden" / "environ 2 mois"), which
  the actor converts to an approximate ISO date. The original text is kept
  in `postedAtRaw`. Germany and the Netherlands return an exact timestamp.
- **Germany/Netherlands pagination is fixed at 10 results per page.**
  Verified live: the search API accepts a larger `limit` on the very first
  page, but silently returns zero items on any later page unless `limit`
  is 10 — the same page size the real Manpower site itself always uses.
- **Location filtering is client-side.** Manpower's search doesn't expose
  a reliable structured location parameter this actor can drive
  server-side.

### Related scrapers

Building a European staffing dataset? These sibling actors follow the
same approach:

- **Adecco Scraper** — one shared platform across Belgium, Netherlands, France, Spain, Italy and Poland
- **Randstad Belgium Scraper** — the world's largest staffing agency, Belgian market
- **VDAB Scraper** — Flemish public employment service
- **Le Forem Scraper** — Walloon public employment service
- **StepStone Scraper** — commercial job board, multiple European markets

### Disclaimer

This actor collects publicly available data from Manpower for legitimate
research and aggregation use. Respect Manpower's terms of service and
applicable data protection law when using the output.

# Actor input Schema

## `country` (type: `string`):

Manpower market to search. Belgium has separate Dutch and French listings. France is not supported (manpower.fr blocks direct access).

## `searchQuery` (type: `string`):

Keyword to search for, in the local language (e.g. 'lager' for Germany, 'magazijn' for Belgium/Netherlands, 'entrepôt' for French Belgium). Leave empty to return all current listings for the selected country.

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

Optional city to filter results by. Applied client-side against the listing's location text — Manpower's search does not expose a reliable structured location filter we can drive server-side.

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

Maximum number of job listings to return.

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

Proxy settings. Manpower's Germany/Belgium/Netherlands sites do not require a residential proxy — Apify's automatic proxy is sufficient.

## Actor input object example

```json
{
  "country": "DE",
  "searchQuery": "lager",
  "maxResults": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "searchQuery": "lager",
    "maxResults": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/manpower-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 = {
    "searchQuery": "lager",
    "maxResults": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/manpower-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 '{
  "searchQuery": "lager",
  "maxResults": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call studio-amba/manpower-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/manpower-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/uBCrnDAkqy4dgeBqa/builds/n9UNuENmEX5zgtku4/openapi.json
