# XING Jobs Scraper | Every Job, Salaries & Recruiter Contacts (`corvuslab/xing-jobs-scraper`) Actor

Scrape XING jobs in Germany, Austria and Switzerland: every job in a search, past the 1,000-job limit. Full description, salary range or XING estimate, recruiter emails and phones. Companies mode: profiles of the employers hiring, with size, industry, HQ and website. Incremental alerts.

- **URL**: https://apify.com/corvuslab/xing-jobs-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

### What does XING Jobs Scraper do?

XING Jobs Scraper extracts job listings from **[xing.com](https://www.xing.com/jobs)**, the professional network for **Germany, Austria and Switzerland**, and it reads **every job in a search**, not just the first page or two. XING itself lists at most **1,000 jobs for any one search**; this Actor goes past that cap and returns the whole result set. In testing, a nationwide "python" search came back with **4,440 jobs in under a minute**. Each job is a clean record with up to **79 fields**: the full description, **XING's own summary** (responsibilities and qualifications), keywords, **salary on about 87% of jobs**, company size and industry, and the recruiter emails and phones written in the posting. Export to JSON, CSV or Excel, use the API, or hand the data to an AI agent. No code needed.

Give it search terms, cities and any of XING's filters (employment type, career level, 22 disciplines, remote / hybrid / on-site, posted within, salary range, country, industry), or paste XING search and job URLs. Every matching job comes back with its company, location, salary, apply link and full description. The full details are included with every job, so there is no separate enrichment step to switch on and nothing extra per job. Start it with no input at all and it returns the newest jobs on XING.

> New to Apify? Sign up free and use the included monthly platform credit to try this Actor. No credit card needed.

**Why this scraper**

- 📚 **Complete searches**: big searches are read in full, past the 1,000 jobs XING shows per search.
- 🧠 **Full details included**: description, XING summary, keywords and contacts come with every job at no extra charge.
- 💶 **Honest salary data**: `salaryType` tells a posted salary range apart from XING's salary estimate (min / median / max).
- ⚡ **Fast and low-cost**: thousands of jobs per minute, so large runs stay cheap.
- ♻️ **Cheap to monitor**: incremental mode charges only for NEW, UPDATED and REAPPEARED jobs. Unchanged jobs cost nothing.
- 🤖 **AI and API-ready**: compact output, MCP-friendly, one-click integrations.

***

### What data can you extract from XING?

Every record carries **79 fields**, grouped like this:

| Group | What you get |
|---|---|
| **Job** | `title`, `url`, `id`, `xingId`, `slug`, `jobCode`, `language`, `postedAt`, `refreshedAt`, `validThrough`, `isPaid`, `isTopJob` |
| **Classification** | `employmentType`, `careerLevel`, `discipline`, `industry`, each with a stable `…Code` alongside the label, plus `workplaceType` (remote / hybrid / on-site), `remoteOptions`, `isRemote` |
| **Location** | `location`, `city`, `postalCode`, `street`, `region` (federal state / canton), `country`, `countryCode`, `locations` (every site of a multi-site job) |
| **Salary** | `salaryMin`, `salaryMedian`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryType` (range / fixed / estimate), `salaryIsEstimate`, `salaryText` |
| **Description & XING summary** | `description` as plain text, `descriptionHtml`, `descriptionMarkdown`, `summary`, `responsibilities[]`, `qualifications[]`, `keywords[]`, `descriptionHeaderImage` |
| **Company** | `company`, `companyId`, `companyUrl` (XING page), `companyLogo`, `companySize`, `companyIndustry`, `companyCity`, `companyCountry`, `companyWebsite` |
| **Contacts & apply** | `contactEmail`, `extractedEmails`, `extractedPhones`, `extractedUrls`, `socialProfiles`, `applyUrl`, `applicationType` (XING / external / email / message), `easyApply`, `redirectsToExternalSite` |
| **Monitoring** | `changeType`, `firstSeenAt`, `lastSeenAt`, `previousSeenAt`, `expiredAt`, `isRepost`, `repostOfId`, `repostDetectedAt`, `contentHash`, plus `searchKeyword` / `searchLocation` showing which search found the job |

***

### Key features

- 📚 **Full-depth search**: XING shows no more than 1,000 jobs per search. When a search is bigger, this Actor still returns every matching job, de-duplicated. A nationwide "python" search returned 4,440 jobs in under a minute.
- 🧠 **Full details at no extra charge**: every job includes the full description (text, HTML and Markdown), XING's summary with responsibilities and qualifications, keywords and the contacts in the posting. You pay the same per job whether details are on or off.
- 💶 **Posted salary vs XING estimate, kept apart**: about 87% of jobs carry a salary. `salaryType` and `salaryIsEstimate` show whether the employer posted a range or XING estimated one (with a median), so the two never get mixed up in your analysis.
- 🎚️ **All of XING's filters**: employment type, career level, 22 disciplines, workplace (remote / hybrid / on-site), posted within 24 h / 7 d / 30 d, minimum and maximum salary, country (DE / AT / CH) and industry. Jobs you filter out never reach your dataset, so you never pay for them.
- 📍 **City + radius search**: search one or more cities with a radius from "city only" up to 200 km, or paste any XING search URL with your filters already set.
- 📇 **Recruiter contacts for lead generation**: emails, phones, URLs and social profiles pulled from the job text, plus the company website. `requireContact` keeps only the postings that name an email, a phone or both.
- ♻️ **Incremental monitoring**: schedule it and get only what changed (NEW / UPDATED / REAPPEARED / EXPIRED). Unchanged jobs are not emitted and not charged. Re-posts of the same job under a new ID can be flagged or skipped.
- 🔔 **Notifications**: Telegram, Slack, Discord or any webhook (n8n / Make / Zapier).
- 🗣️ **English or German labels**: employment type, career level, discipline and country in either language. Job texts stay exactly as the employer wrote them.
- 🤖 **AI-ready**: compact and drop-empty output modes keep payloads small for LLMs and MCP.

***

### 🚀 How to scrape XING

1. Open the Actor and enter one or more **search terms** (e.g. `Softwareentwickler`), add **locations** like `Berlin` or `Zürich`, or paste a XING search URL.
2. Pick any **filters**: employment type, career level, discipline, workplace, posted within, salary, country.
3. Set **Max results** (0 = every matching job).
4. (Optional) Turn on **incremental mode** and a **notification** channel, then **Schedule** it.
5. Click **Start**, and download the results as **JSON, CSV or Excel**, or pull them from the **API**.

No XING account, no login, no cookies. It runs out of the box.

#### Quick-start example input

```json
{
  "searchTerms": ["Data Engineer"],
  "locations": ["München"],
  "radiusKm": "50",
  "remoteOptions": ["hybrid", "full_remote"],
  "postedWithin": "7d",
  "maxResults": 200
}
```

This returns up to 200 data engineering jobs within 50 km of Munich posted in the last week, hybrid or fully remote only. Each comes with its salary, company profile, XING summary and full description, ready to drop into a spreadsheet or an outreach list.

***

### Input

Configure it in the visual editor, no code needed, or pass JSON via the API. **37 inputs** are available, grouped exactly as in the editor.

#### 🔎 Search

| Field | Type | What it does |
|---|---|---|
| `searchTerms` | array | Job titles, skills or companies, e.g. `Softwareentwickler`, `Marketing Manager`, `SAP`. Each term is its own search. Leave empty to list every job. |
| `locations` | array | Cities such as `Berlin`, `München`, `Wien`, `Zürich`. Every term runs in every location; results are merged and de-duplicated. A country name becomes a country filter. |
| `radiusKm` | enum | Site default, city only, 10, 20, 30, 50, 75, 100, 150 or 200 km around each location. |
| `startUrls` | array | XING job search URLs (your on-site filters are kept) or single job URLs. Replaces the search terms when given. |
| `maxResults` | integer | Cap on jobs across all searches (default 50). `0` = no limit; big searches are read in full. |

#### 🎚️ Filters

Several values inside one filter widen the search (OR); different filters narrow it (AND).

| Field | Type | What it does |
|---|---|---|
| `employmentTypes` | array | `full_time`, `part_time`, `freelance`, `student`, `temporary`, `seasonal`, `volunteer`. |
| `careerLevels` | array | `student_intern`, `entry_level`, `professional`, `manager`, `executive`, `senior_executive`. |
| `disciplines` | array | 22 professional fields, e.g. `it_software`, `engineering_technical`, `sales_commerce`, `marketing_advertising`, `finance_accounting`, `consulting`, `hr`, `legal`. |
| `remoteOptions` | array | `full_remote`, `hybrid`, `on_site`. |
| `postedWithin` | enum | `any`, `24h`, `7d`, `30d`. |
| `salaryMin` / `salaryMax` | integer | Yearly salary bounds in EUR. |
| `countries` | array | `DE`, `AT`, `CH`. |
| `industries` | array | Keep jobs whose industry (the job's or the company's) contains one of these words, e.g. `Banking`, `Automotive`, `Pharma`. |

#### 🎯 Lead generation

| Field | Type | What it does |
|---|---|---|
| `requireContact` | enum | `off`, `email`, `phone`, `either` or `both`. Keeps only postings that name a recruiter email and/or phone. Skipped jobs are not charged. |

#### 📄 Output

| Field | Type | What it does |
|---|---|---|
| `includeDetails` | boolean | Full description, XING summary, keywords and contacts (on by default). Turn off for the smallest records. |
| `descriptionFormat` | enum | `all`, `text`, `html` or `markdown`. |
| `descriptionMaxLength` | integer | Cut descriptions to this many characters (0 = full length). |
| `language` | enum | `en` or `de` for labels such as employment type, career level and discipline. |
| `compact` | boolean | Core fields only. Ideal for AI agents and MCP clients. |
| `excludeEmptyFields` | boolean | Drop null and empty fields for cleaner output. |

#### ♻️ Incremental monitoring

| Field | Type | What it does |
|---|---|---|
| `incrementalMode` | boolean | Track jobs between runs and tag each with a `changeType`. Unchanged jobs are skipped and cost nothing. |
| `stateKey` | string | Stable name for the tracked search (derived from your settings if blank). |
| `emitUnchanged` / `emitExpired` | boolean | Also emit UNCHANGED jobs, or a record for every job that has disappeared. |
| `skipReposts` | boolean | Leave out jobs that are re-posts of one seen before (same title, company and location, new ID). |

#### 🔔 Notifications

Credentials are secret inputs: encrypted at rest, masked in the UI and never written to the run log.

| Field | Type | What it does |
|---|---|---|
| `telegramToken` + `telegramChatId` | string | Telegram bot token + chat or channel ID. |
| `slackWebhookUrl` / `discordWebhookUrl` | string | Incoming webhook URL. |
| `webhookUrl` + `webhookHeaders` | string / object | POST the matched jobs as JSON anywhere: n8n, Make, Zapier. |
| `notificationLimit` | integer | Jobs listed per message (1–20, default 5). |
| `notifyOnlyChanges` | boolean | With incremental mode, alert only on NEW, UPDATED and REAPPEARED jobs. |

#### ⚙️ Advanced

| Field | Type | What it does |
|---|---|---|
| `proxyConfiguration` | object | Optional. The Actor works without one; turn it on only if your runs are refused. |
| `maxRequestRetries` | integer | Retries per failed request (0–10, default 3). |
| `ignoreUrlFailures` | boolean | Skip start URLs that can't be read instead of failing the run. |

#### More example inputs

A senior IT recruiting list across Austria and Switzerland, only postings with a recruiter email:

```json
{
  "searchTerms": ["Java", "Cloud Architect"],
  "countries": ["AT", "CH"],
  "careerLevels": ["professional", "manager"],
  "disciplines": ["it_software"],
  "requireContact": "email",
  "maxResults": 0
}
```

A daily monitor of new finance jobs in Frankfurt with a salary floor, alerting a Slack channel:

```json
{
  "searchTerms": ["Controller"],
  "locations": ["Frankfurt am Main"],
  "radiusKm": "30",
  "salaryMin": 60000,
  "incrementalMode": true,
  "notifyOnlyChanges": true,
  "slackWebhookUrl": "https://hooks.slack.com/services/..."
}
```

Paste a search you built on XING, or single job URLs:

```json
{
  "startUrls": [
    { "url": "https://www.xing.com/jobs/search?keywords=Projektmanager&location=Hamburg" },
    { "url": "https://www.xing.com/jobs/berlin-software-engineer-158507933" }
  ],
  "descriptionFormat": "markdown"
}
```

***

### Output

Each dataset item is one XING job. Every record carries the core job, company, location and salary fields; **Include full details** (on by default) adds the description, XING's summary, keywords and the contacts found in the posting. A real record (descriptions shortened):

```json
{
  "id": "158548413",
  "title": "Teamleiter (m/w/d) Unternehmensberatung Versicherungen",
  "url": "https://www.xing.com/jobs/frankfurt-main-teamleiter-unternehmensberatung-versicherungen-158548413",
  "company": "PBMS PersonalBeratung Matthias Schneider",
  "companyUrl": "https://www.xing.com/pages/pbmspersonalberatungmatthiasschneider",
  "companySize": "1-10 employees",
  "companyIndustry": "HR services and consulting",
  "companyWebsite": "https://www.pbms-frankfurt.de/",
  "location": "Frankfurt am Main, Hessen, DE",
  "city": "Frankfurt am Main",
  "region": "Hessen",
  "countryCode": "DE",
  "workplaceType": "hybrid",
  "isRemote": false,
  "employmentType": "Full-time",
  "careerLevel": "Manager/Supervisor",
  "careerLevelCode": "manager",
  "discipline": "Management and corporate development",
  "industry": "Insurance",
  "salaryMin": 120000.0,
  "salaryMax": 180000.0,
  "salaryMedian": null,
  "salaryCurrency": "EUR",
  "salaryPeriod": "year",
  "salaryType": "range",
  "salaryIsEstimate": false,
  "salaryText": "EUR 120,000 – 180,000",
  "postedAt": "2026-10-14T08:15:21Z",
  "validThrough": "2026-11-13T08:18:16Z",
  "applyUrl": "https://www.xing.com/jobs/frankfurt-main-teamleiter-unternehmensberatung-versicherungen-158548413",
  "applicationType": "xing",
  "easyApply": true,
  "language": "de",
  "description": "Über uns\n\nIm Auftrag einer etablierten mittelständischen und auf Finanzdienstleistungen spezialisierten IT- und Managementberatung … suchen wir Sie als\n\nTeamleiter (m/w/d) Unternehmensberatung Versicherungen …",
  "summary": "Eine etablierte IT- und Managementberatung sucht einen Teamleiter (m/w/d) Unternehmensberatung Versicherungen in Frankfurt am Main. Das Unternehmen ist auf Finanzdienstleistungen spezialisiert und befindet sich auf Wachstumskurs.",
  "responsibilities": [
    "Leitung von Projekten in der Unternehmensberatung.",
    "Beratung zu IT- und Prozessfragen.",
    "Führung und Verantwortung im Team."
  ],
  "qualifications": [
    "Langjährige Erfahrung in Unternehmensberatung.",
    "Führungs- und Umsatzverantwortung erforderlich.",
    "Guter Überblick über Versicherungsfragen."
  ],
  "keywords": ["teamleitung", "projektmanagement", "beratung", "versicherung", "prozessoptimierung"],
  "contactEmail": "Bewerbung@pbms-frankfurt.de",
  "extractedEmails": ["Bewerbung@pbms-frankfurt.de"],
  "extractedPhones": ["06196 / 99 848 48"],
  "socialProfiles": { "xing": "https://www.xing.com/pages/pbmspersonalberatungmatthiasschneider" },
  "searchKeyword": "Manager",
  "source": "xing.com",
  "scrapedAt": "2026-10-18T22:38:12.039506+00:00"
}
```

Descriptions also come as `descriptionHtml` and `descriptionMarkdown`. In incremental mode each record also carries `changeType` (NEW / UPDATED / REAPPEARED / UNCHANGED / EXPIRED) with `firstSeenAt`, `lastSeenAt` and the repost fields.

#### Data fields

- **Core**: `title`, `url`, `id`, `company`, `location`, `workplaceType`, `employmentType`, `careerLevel`, `discipline`, `industry`, `postedAt`, `validThrough`.
- **Salary**: `salaryMin` / `salaryMedian` / `salaryMax`, currency, period, `salaryType` and `salaryIsEstimate`. A posted range has no median; an XING estimate does.
- **Details** (with `includeDetails`): `description` (text / HTML / Markdown), `summary`, `responsibilities`, `qualifications`, `keywords`, `descriptionHeaderImage`.
- **Contacts & signals**: `contactEmail`, `extractedEmails`, `extractedPhones`, `extractedUrls`, `socialProfiles`, `easyApply`, `isTopJob`, `isPaid`.
- **Company**: `companySize`, `companyIndustry`, `companyCity`, `companyCountry`, `companyWebsite`, `companyLogo`, `companyUrl`.
- **Apply**: `applyUrl`, `applicationType`, `redirectsToExternalSite`.

Every field is present in standard mode (missing values are `null`). **Compact mode** returns 17 core fields only, for lean AI and MCP payloads; **`excludeEmptyFields`** drops empties entirely. The Output tab also ships four ready-made views: **Overview**, **Salaries** (min / median / max with posted-vs-estimate), **Companies & contacts**, and **Changes (incremental)**.

***

### ♻️ How to monitor XING with incremental mode

Schedule the Actor and turn on **incremental mode**: each run compares against the last and emits only **NEW, UPDATED and REAPPEARED** jobs, plus **EXPIRED** ones if you ask for them. Unchanged jobs are recognised and left out, so they are never charged.

| | First run (baseline) | Next run (nothing changed) |
|---|---|---|
| Jobs checked | all | all |
| Records emitted & billed | all | **none** |
| Alerts sent | all matches | **none** |

Your cost after the baseline scales with how much XING changes, not with how much you watch:

| Daily churn | of 1,000 tracked | billable records | you save |
|---|---|---|---|
| 5 % | 1,000 | 50 | **95 %** |
| 15 % | 1,000 | 150 | **85 %** |
| 30 % | 1,000 | 300 | **70 %** |

Jobs that disappear and come back are tagged **REAPPEARED**, so a re-opened role isn't mistaken for a new one. With `skipReposts`, a job re-published under a new ID (same title, company and location) is left out, so it doesn't count as fresh demand.

#### Setting up scheduled monitoring

1. Configure your search terms, locations and filters.
2. Turn on **Incremental mode** (leave `maxResults` at 0 if you want EXPIRED jobs reported).
3. Run it once to seed the baseline.
4. Open the **Schedules** tab and set a recurring run, e.g. every morning.
5. Add a notification channel with **Notify only about changes** on.

***

### 🔔 How to set up XING alerts

Get pinged the moment a matching XING job appears. Fill in only the channels you want:

| Channel | What to configure |
|---|---|
| ✈️ **Telegram** | `telegramToken` (from @BotFather) + `telegramChatId` |
| 💬 **Slack** | `slackWebhookUrl` (Incoming Webhook URL) |
| 🎮 **Discord** | `discordWebhookUrl` (channel webhook URL) |
| 🪝 **Webhook** | `webhookUrl` receives the matched jobs as structured JSON, ideal for n8n / Make / Zapier |

Each message lists up to `notificationLimit` jobs with title, company, salary and link. Every channel fires independently, so a broken channel can't stop the scrape or the others. Pair **incremental mode** with **notify only about changes** to hear only about genuinely new jobs, with no duplicates across runs.

***

### 💡 What can you do with XING data?

#### Recruiting and sourcing in the DACH market

Agencies and in-house recruiters see which companies are hiring for a role in Germany, Austria or Switzerland right now, at full depth rather than a sample. The career level, discipline and workplace fields let you segment the list in seconds.

#### Lead generation for staffing and B2B sales

A company with open roles has budget and a need. Combine `companySize`, `companyIndustry` and `companyWebsite` with the recruiter emails and phones in the posting, and use `requireContact` to keep only reachable leads.

#### Salary benchmarking

With salary on about 87% of jobs and a clear posted-vs-estimate flag, you can build pay bands by city, career level and discipline. Use the posted ranges for hard evidence and XING's estimates (with median) for wider coverage.

#### Labour-market and competitor research

Track hiring volume by discipline, region or employer over time. The full-depth read means your counts reflect the real market, not the 1,000-job slice XING shows.

#### Job alerts and job boards

Feed a niche job board, a Slack channel or a newsletter with fresh DACH roles every day. Incremental mode delivers only new jobs, so nothing is posted twice.

#### Skills and requirement analysis

The `keywords`, `responsibilities` and `qualifications` arrays turn thousands of German-language postings into structured skill data. This is useful for training programmes, workforce planning and HR tech.

#### Feed AI agents and LLM pipelines

Compact JSON goes straight into an LLM context, an MCP tool or a vector store. XING's summary plus `excludeEmptyFields` and compact mode keep token costs low.

***

### 💰 How much does it cost to scrape XING?

This Actor uses Apify's **pay-per-event** model: a small fee when a run starts, plus a fee for each job in your dataset. See the Actor's **Pricing** tab for the current numbers. They're rendered live, so this page never goes stale.

The full description, XING summary, keywords and contacts are part of every job. There is **no enrichment add-on** and no second charge for details. The Actor is lightweight and fast, which is why the per-job fee can sit at the low end of the market. Three things cut your bill further:

- **Filters**: jobs you filtered out never reach your dataset and are never billed.
- **`requireContact`**: postings without the contact you need are skipped and not charged.
- **Incremental mode**: after the baseline you pay only for what changed (see the table above).

***

### 🔌 Integrations & export

Export to **JSON, CSV, Excel** or an HTML table, or pull from the **REST API** and the **JavaScript / Python** clients. Runs on a **schedule**, connects to **Google Sheets, Slack, Make, Zapier and n8n**, and works as an **MCP tool** for AI agents. Compact mode keeps token usage small.

Also covering the DACH job market: [Arbeitsagentur Jobs Scraper](https://apify.com/corvuslab/arbeitsagentur-jobs-scraper) for Germany's largest job board, [StepStone Job Scraper](https://apify.com/corvuslab/stepstone-jobs-scraper) for DE + AT jobs, and [kununu Company Profile Scraper](https://apify.com/corvuslab/kununu-scraper) for the employer ratings that pair with XING's company data.

***

### 🔗 Using the API

Run this Actor from your own code. Example with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "searchTerms": ["Softwareentwickler"],
    "locations": ["Berlin"],
    "radiusKm": "30",
    "maxResults": 100,
}

run = client.actor("corvuslab/xing-jobs-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["company"], item["salaryText"])
```

It also works with the JavaScript/TypeScript client, the Apify CLI and the REST API.

***

### ❓ FAQ

**Do I need a XING account or login?** No. The Actor reads XING's public job listings without an account, cookies or a Premium membership. It runs out of the box.

**How many jobs can I get from one XING search?** All of them. XING itself shows at most 1,000 jobs for any one search; when a search is bigger, the Actor still returns every matching job, de-duplicated. Set `maxResults` to `0` for no limit. XING doesn't show a total count for logged-out searches, so the size of your dataset is the real number.

**Why do some jobs have a salary and others don't, and what is `salaryType`?** About 87% of jobs carry a salary. Roughly a quarter of all jobs have a range the employer posted (`salaryType: "range"` or `"fixed"`); most of the rest carry XING's own salary estimate (`salaryType: "estimate"`, `salaryIsEstimate: true`), which also fills `salaryMedian`. The remaining ~13% have neither, so the salary fields are `null`. Filter on `salaryIsEstimate` if you only want employer-posted pay.

**How many jobs include a recruiter email or phone?** About 28% of postings name an email and about 28% a phone number in the job text; the company website is present on about 15%. XING has no structured contact-person field, so names aren't returned. Use `requireContact` to keep only reachable postings, and skipped jobs aren't charged.

**Why is `summary` (or `responsibilities` / `qualifications`) empty on some jobs?** These come from XING's own job summary, which XING writes for roughly half of all postings. The full `description` is present on every job.

**Are the job texts in German?** Mostly, yes. Around 97% of XING postings are written in German and are returned exactly as published. The `language` input switches the labels (employment type, career level, discipline, country) between English and German, for example "Full-time" or "Vollzeit".

**How should I write locations?** Use the city name as XING spells it: `München` or `Munich` work, `Muenchen` does not. A country name such as `Österreich` or `Switzerland` becomes a country filter. A place XING doesn't recognise is skipped with a warning in the log instead of quietly searching everywhere.

**Why are Austria- or Switzerland-only runs slower?** XING's search is Germany-heavy. A country filter on its own means scanning more jobs to find the AT or CH ones. Add a city such as `Wien` or `Zürich` for the fastest runs.

**Is the salary filter exact?** XING applies `salaryMin` / `salaryMax` loosely and counts its own estimates too, so you may see jobs just outside your range. The salary fields in each record let you filter precisely afterwards.

**Can I get only new jobs on a schedule?** Yes. Turn on incremental mode and schedule it; each run emits only NEW, UPDATED and REAPPEARED jobs and can notify your channel. Unchanged jobs cost nothing.

**Is it good for AI agents?** Yes. Enable compact mode; the output is MCP-friendly and drops empty fields.

***

### ⚖️ Is it legal to scrape XING?

This Actor collects only **publicly available** job listings, the same ones anyone can see on xing.com without logging in. It does not access member profiles, private messages or anything behind a login. You're responsible for how you use the data, in particular any personal information such as a recruiter's email or phone, and for complying with XING's terms and applicable law, including the GDPR where it applies. Not affiliated with, endorsed by or sponsored by XING or New Work SE.

***

**Keywords:** xing scraper · xing jobs scraper · xing job scraper · xing api · xing.com scraper · scrape xing jobs · xing job listings · dach job market · germany jobs scraper · austria jobs · switzerland jobs · salary data germany · recruiter contacts · lead generation · job monitoring · export to CSV · export to Excel · MCP tool for AI agents

# Changelog

This Actor's version history is a separate document: https://apify.com/corvuslab/xing-jobs-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

Job titles, skills or companies, e.g. "Softwareentwickler", "Marketing Manager" or "SAP". Each term is its own search. Leave empty to list every job.

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

Cities to search in, e.g. "Berlin", "München", "Wien" or "Zürich". Leave empty to search everywhere.

## `radiusKm` (type: `string`):

How far around each location to search. Only used together with a location.

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

Paste XING job search URLs (xing.com/jobs/search?keywords=…) or single job URLs (xing.com/jobs/berlin-software-engineer-158507933). Search URLs keep the filters you set on the site. When given, they replace the search terms above.

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

Maximum number of jobs to return across all searches. Set 0 for no limit — big searches are read in full, even past what the site shows in one search.

## `employmentTypes` (type: `array`):

Keep only these employment types.

## `careerLevels` (type: `array`):

Keep only these seniority levels.

## `disciplines` (type: `array`):

Keep only jobs in these professional fields.

## `remoteOptions` (type: `array`):

Keep only fully remote, hybrid or on-site jobs.

## `postedWithin` (type: `string`):

Keep only jobs published recently.

## `salaryMin` (type: `integer`):

Keep jobs whose salary reaches at least this much per year (EUR). XING applies this loosely and counts its own salary estimates too.

## `salaryMax` (type: `integer`):

Keep jobs whose salary starts at or below this much per year (EUR).

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

Keep only jobs located in these countries. Combine with a location for the fastest runs.

## `industries` (type: `array`):

Keep only jobs whose industry contains one of these words, e.g. "Banking", "Automotive" or "Pharma" (matches the job's or the company's industry).

## `requireContact` (type: `string`):

off = keep everything; email / phone = require that channel; either = at least one; both = email and phone. Skipped jobs are not charged.

## `includeDetails` (type: `boolean`):

Add the full job description, XING's summary, keywords and the contacts found in the posting. Turn off for the smallest records.

## `descriptionFormat` (type: `string`):

Which representation(s) of the job description to include.

## `descriptionMaxLength` (type: `integer`):

Cut descriptions to this many characters. 0 = full length.

## `language` (type: `string`):

Language of labels such as employment type, career level, discipline and country. Job texts stay as the employer wrote them.

## `compact` (type: `boolean`):

Emit only the core fields. Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each record.

## `incrementalMode` (type: `boolean`):

Track jobs between runs and tag every record with a changeType (NEW / UPDATED / REAPPEARED / UNCHANGED / EXPIRED). Unchanged jobs are skipped and cost nothing.

## `stateKey` (type: `string`):

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit jobs that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Emit a record for each job that was there last run and is gone now. Only reported by runs that read the whole search.

## `skipReposts` (type: `boolean`):

Leave out jobs that look like a re-post of one seen before (same title, company and location under a new id).

## `telegramToken` (type: `string`):

Bot token from @BotFather.

## `telegramChatId` (type: `string`):

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL.

## `discordWebhookUrl` (type: `string`):

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with the matched jobs — works with n8n, Make and Zapier.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}.

## `notificationLimit` (type: `integer`):

How many jobs to list in each notification message.

## `notifyOnlyChanges` (type: `boolean`):

With incremental mode on, notify only about NEW, UPDATED and REAPPEARED jobs.

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

Optional. The actor works without a proxy; turn one on only if your runs are refused.

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

How many times to retry a failed request before giving up on it.

## `ignoreUrlFailures` (type: `boolean`):

Skip start URLs that cannot be interpreted instead of failing the whole run.

## Actor input object example

```json
{
  "searchTerms": [
    "Software Engineer"
  ],
  "radiusKm": "default",
  "maxResults": 50,
  "postedWithin": "any",
  "requireContact": "off",
  "includeDetails": true,
  "descriptionFormat": "all",
  "descriptionMaxLength": 0,
  "language": "en",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "skipReposts": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 3,
  "ignoreUrlFailures": true
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `allItems` (type: `string`):

No description

## `salaries` (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 = {
    "searchTerms": [
        "Software Engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/xing-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 = { "searchTerms": ["Software Engineer"] }

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/xing-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 '{
  "searchTerms": [
    "Software Engineer"
  ]
}' |
apify call corvuslab/xing-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,corvuslab/xing-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/DaTtkDoBQXJdsgxIs/builds/tnCFr4MOcHrvumqJ5/openapi.json
