# Xing Jobs Scraper - DACH Job Listings with Salaries (`mina_safwat/xing-jobs-scraper`) Actor

Scrapes job listings from any Xing jobs search link or job ad (Germany, Austria, Switzerland) with every filter kept: title, company, place, remote option, employment type, career level, salary range or Xing's salary estimate, dates, apply link and the full description.

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

## Pricing

$0.80 / 1,000 jobs

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** collects **job listings from [Xing](https://www.xing.com/jobs)**, the leading professional network and job board for **Germany, Austria and Switzerland (DACH)**. Search on Xing as you normally would, paste the link, and get every job as a clean row: **title, company, city and region, remote option, employment type, career level, discipline, industry, salary range or Xing's own salary estimate, posted and expiry dates, apply link and the full job description**.

**Every filter in your link is kept**: keywords, place and radius, employment type, career level, remote option, discipline, industry and the rest of Xing's filters. The Actor asks Xing's own job search for exactly the search in your link, so you get the jobs the website shows, in the same order. Xing's topic pages (such as `xing.com/jobs/t-python`) and single job ads work too.

Try it with the prefilled search: open the Actor, click **Start**, and 40 Python jobs in Berlin, with salaries and full descriptions, are ready in **under 10 seconds**. Running on the Apify platform also gives you API access, scheduled runs, integrations (Google Sheets, Make, Zapier, Slack, webhooks) and run monitoring.

### Why scrape Xing jobs?

- **Salary benchmarking.** Most Xing listings carry a salary: the employer's own range or Xing's estimate for the role and place, with a median. You get them as numbers you can sort, chart and average.
- **DACH labour market research.** Track demand by role, city, region, career level, industry and remote share across Germany, Austria and Switzerland.
- **Recruitment and sales leads.** See which companies are hiring, for what and where, with their Xing company page.
- **Job aggregation.** Feed a niche job board, newsletter or internal tool with fresh, structured listings and full descriptions.
- **Monitoring.** Schedule a daily run and keep only the job IDs you have not seen before.

### How to scrape Xing jobs

1. Open [xing.com/jobs](https://www.xing.com/jobs/search) and search: type keywords and a place, then pick any filters.
2. Copy the address from your browser's address bar, for example `https://www.xing.com/jobs/search?keywords=python&location=Berlin&radius=20&employmentType=FULL_TIME.ef2fe9`.
3. Paste it into **Xing search or job links**. Add as many links as you like, one per line.
4. Set **Max jobs per search link** and choose whether to include full descriptions.
5. Click **Start**, then download the results as JSON, CSV, Excel or HTML.

### Input

Everything is set on the Input tab. In JSON, the input looks like this:

```json
{
    "startUrls": [
        "https://www.xing.com/jobs/search?keywords=python&location=Berlin&radius=20&employmentType=FULL_TIME.ef2fe9",
        "xing.com/jobs/t-data-scientist",
        { "url": "https://www.xing.com/jobs/berlin-research-software-engineer-rse-158432056" }
    ],
    "maxItems": 100,
    "includeDescription": true
}
```

| Field | What it does |
|---|---|
| `startUrls` | Xing links, one per line: search result pages (`xing.com/jobs/search?…`), topic pages (`xing.com/jobs/t-python`, `xing.com/jobs/berlin-python`, `xing.com/jobs/software-engineer-jobs-in-berlin`) and single job ads (`xing.com/jobs/<title>-<number>`). `https://` is optional, and API callers can send `{"url": "…"}` objects. |
| `maxItems` | Stops after this many jobs from each search link. Default: 100, at most 1,000 (see Tips). A job ad link always gives its one job. |
| `includeDescription` | Adds each job's full description as plain text and HTML. Default: on. The description comes with the search results, so it costs no extra requests; turn it off only for smaller rows. |
| `proxyConfiguration` | Leave empty. The Actor reaches Xing directly and switches to Apify's proxies on its own if Xing turns a request away or hides jobs from an address. Choose a proxy only to send every request through it. |

#### Which filters are kept?

| On Xing | In the link | Example |
|---|---|---|
| Keywords | `keywords=` | `keywords=python` |
| Place and radius | `location=`, `cityId=`, `radius=` (km) | `location=Berlin&radius=20` |
| Employment type | `employmentType=` | `FULL_TIME.ef2fe9`, `PART_TIME.58889d`, `INTERN.dc571c` |
| Career level | `careerLevel=` | `3.2ebf16` (professional), `4.83b992` (manager) |
| Remote option | `remoteOption=` | `FULL_REMOTE.050e26`, `PARTLY_REMOTE.ca71ca`, `NON_REMOTE.3ca273` |
| Discipline, industry, city, country, company, benefits | `discipline=`, `industry=`, `city=`, `country=`, `company=`, `benefit=`, `benefitEmployeePerk=`, `benefitWorkingCulture=` | `discipline=1007.b61d22` |
| Page | `page=` | `page=3` starts at the third page of results |

Several values can be given comma-separated or by repeating the parameter. Like Xing's own site, a search for **fully remote** jobs only ignores the place. Other parameters (such as tracking codes) are ignored. Xing's `sort=` setting is passed on as the site does; in our tests Xing returned the same order either way.

### Output

Each job becomes one row. Here is a real one from the prefilled search, with long texts shortened:

```json
{
    "jobId": 149675415,
    "title": "Software Developer für KI-Projekte (m/w/d)",
    "company": "Pexon Consulting GmbH",
    "companyId": 1974086,
    "companyUrl": "https://www.xing.com/pages/pexon-consulting-gmbh",
    "companyLogo": "https://www.xing.com/imagecache/public/scaled_original_image/eyJ1dWlkIjoiZGM4NWFhNDYt...",
    "city": "Berlin",
    "zip": "10243",
    "street": "Gubener Straße 47",
    "region": "Land Berlin",
    "country": "DE",
    "remote": "Partly remote",
    "employmentType": "Full-time",
    "careerLevel": "Professional/Experienced",
    "discipline": "IT and software development",
    "industry": "Other services",
    "salaryMin": 56000,
    "salaryMax": 74500,
    "salaryMedian": 63000,
    "salaryCurrency": "EUR",
    "salaryType": "estimate",
    "postedAt": "2026-01-20T08:14:00Z",
    "refreshedAt": "2026-01-20T08:14:00Z",
    "expiresAt": "2027-01-20T08:14:03Z",
    "language": "de",
    "applyUrl": "https://www.xing.com/jobs/berlin-software-developer-ki-projekte-149675415",
    "applyOnXing": true,
    "url": "https://www.xing.com/jobs/berlin-software-developer-ki-projekte-149675415",
    "descriptionText": "Du möchtest moderne Backend-Systeme entwickeln und gleichzeitig an innovativen KI-Projekten mitarbeiten? In dieser Rolle entwickelst du skalierbare Cloud-Anwend...",
    "descriptionHtml": "<p>Du möchtest moderne Backend-Systeme entwickeln und gleichzeitig an innovativen <strong>KI-Projekten</strong> mitarbeiten? In dieser Rolle...",
    "searchUrl": "https://www.xing.com/jobs/search?keywords=python&location=Berlin",
    "scrapedAt": "2026-10-11T07:39:23Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. The Output tab has two views: **Jobs** (the main columns) and **Full details**.

### Data fields

| Field | Description |
|---|---|
| `jobId` | Xing's job number (the number at the end of the job's link). |
| `title` | Job title. |
| `company` | The employer as the job ad names it. |
| `companyId`, `companyUrl`, `companyLogo` | The employer's Xing company number, company page and logo. Empty when the ad is not linked to a Xing company page. |
| `city`, `zip`, `street`, `region`, `country` | Where the job is. Street and postal code only when the employer gave them; `country` is a two-letter code such as `DE`, `AT` or `CH`. |
| `remote` | `Full remote`, `Partly remote` or `On-site`, as the employer set it; a few ads name several, comma-separated. |
| `employmentType` | For example `Full-time`, `Part-time`, `Student`, `Self-employed`, `Temp`. |
| `careerLevel` | For example `Entry Level`, `Professional/Experienced`, `Manager/Supervisor`. |
| `discipline`, `industry` | Xing's job field and the employer's industry. |
| `salaryMin`, `salaryMax` | Gross pay as shown on Xing. Xing's estimates are yearly; an employer's own range or figure is stored without a period and is usually yearly, but can be monthly or hourly. For an exact figure both hold the same amount. Empty when Xing shows no salary. |
| `salaryMedian` | The median of Xing's estimate (only for `salaryType` `estimate`). |
| `salaryCurrency` | Currency code: `EUR`, or `CHF` for many Swiss jobs. |
| `salaryType` | `estimate` (Xing's own estimate for the role and place), `range` (the employer's range) or `exact` (the employer's single figure). |
| `postedAt`, `refreshedAt` | When the ad was published and last refreshed, in UTC. |
| `expiresAt` | When the ad is due to go offline, in UTC. |
| `language` | The language the ad is written in, such as `de` or `en`. |
| `applyUrl` | Where to apply: the employer's own application page, or the Xing job ad when applications go through Xing. |
| `applyOnXing` | `true` when applications go through Xing itself rather than the employer's website. |
| `url` | Link to the job ad on Xing. |
| `descriptionText`, `descriptionHtml` | The full job description as plain text and as HTML. \* |
| `searchUrl` | The search link you pasted that found this job; empty for job ad links. |
| `scrapedAt` | When the job was collected, in UTC. |

\* Only when **Include full job descriptions** is on; with it off, these fields are left out of the rows.

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

The Actor uses **pay-per-event** pricing: you pay a small fixed price for each job saved, and the exact price is on the **Pricing** tab. **Full descriptions are included at no extra charge**, because Xing sends them with the search results. The Actor uses plain HTTP requests (no browser) and 512 MB of memory, and each request brings back up to 20 complete jobs, so runs are quick and light.

You are never charged for links that return nothing: a search with no jobs, an expired job ad or a link that is not from Xing is listed in the run's `FAILED_INPUTS` record instead. If you set a maximum cost for a run, the Actor stops as soon as it is reached.

### Tips for scraping Xing

- **Xing serves at most 1,000 jobs per search.** That is Xing's own limit (50 pages of 20). Xing's result pages also repeat some jobs, so a broad search gives roughly 700 to 800 distinct jobs (in our tests 748 for "manager"); each is saved once. To collect more, split a broad search into several links, for example one per city, career level or employment type; jobs found by more than one link are saved only once.
- **Let Xing filter for you.** Narrow the search on Xing before copying the link; you only collect (and pay for) the jobs that match.
- **Monitor new jobs.** Schedule the Actor daily on your search and keep only job IDs you have not seen before; `postedAt` tells you when each job went online.
- **Speed.** 100 jobs take about 5 seconds; a full 1,000-slot search about 10 to 15 seconds.

### FAQ, disclaimers and support

**Which links work?** Xing job search pages (`xing.com/jobs/search?…`, including `/jobs/search/ki`), Xing's topic pages (`/jobs/t-<keyword>`, `/jobs/<city>-<keyword>`, `/jobs/<keyword>-jobs-in-<city>`) and single job ads (`/jobs/<title>-<number>`). Other Xing pages (profiles, company pages, news) are listed in `FAILED_INPUTS` with the reason.

**Why do topic pages give different jobs from the search box?** Xing itself turns a topic page such as `xing.com/jobs/berlin-python` into the keywords "Berlin Python"; the Actor does the same, so you get the jobs that page shows.

**Xing finds jobs even for nonsense keywords?** Xing's search is semantic: it returns the closest matches rather than nothing, on the website too. Use filters to keep results tight.

**What happens to links that return nothing?** They are not saved as rows, so you are not charged for them. Each is listed with its reason in the `FAILED_INPUTS` record of the run's key-value store, and the run's status message gives the counts. A link with a filter value Xing does not recognise (for example a hand-edited one) is reported the same way. A run fails only when Xing could not be reached for any of your links.

**What are "hidden placeholders" in the status message?** Xing hides some jobs from visitors outside Germany, Austria, Switzerland and the US. The Actor asks again from another address when that happens; any job Xing still hides is skipped (never saved or billed) and counted in the status message.

**Is it legal to scrape Xing?** This Actor collects job listings that employers publish publicly so that people can find and apply for them. It does not log in and does not collect member profiles or candidate data. Listings can still contain a recruiter's name or contact details written by the employer, and their text belongs to the employer; Xing's robots.txt also asks automated clients to stay away from its search API and some search pages. You are responsible for making sure your use complies with Xing's terms and with the laws that apply to you, such as the GDPR and copyright rules for republishing listings. If in doubt, ask a lawyer.

**Found a problem or need something custom?** Open an issue on the **Issues** tab and we will look into it. Custom scrapers and job data feeds are available on request.

# Actor input Schema

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

One link per line. Search on xing.com/jobs with any keywords, place, radius and filters you like (employment type, career level, remote option, discipline, industry, sort order, page), then copy the address bar. Xing's topic pages such as xing.com/jobs/t-python or xing.com/jobs/berlin-python and single job ads such as xing.com/jobs/berlin-python-developer-156675213 work too. Links without https:// are fine.

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

Stops after this many jobs from each search link. Xing serves at most the first 1,000 jobs of any one search; split a bigger search by place or filters. Job ad links always give their one job.

## `includeDescription` (type: `boolean`):

Adds each job's full description as plain text and as HTML. It comes with the search results, so it costs no extra requests; turn it off only for smaller rows.

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

Leave this empty. The Actor reaches Xing directly where it can and switches to Apify's proxies on its own when Xing hides jobs from an address or turns a request away. Choose a proxy here only to send every request through it.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.xing.com/jobs/search?keywords=python&location=Berlin"
  ],
  "maxItems": 40,
  "includeDescription": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrls": [
        "https://www.xing.com/jobs/search?keywords=python&location=Berlin"
    ],
    "maxItems": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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 = {
    "startUrls": ["https://www.xing.com/jobs/search?keywords=python&location=Berlin"],
    "maxItems": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/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 '{
  "startUrls": [
    "https://www.xing.com/jobs/search?keywords=python&location=Berlin"
  ],
  "maxItems": 40
}' |
apify call mina_safwat/xing-jobs-scraper --silent --output-dataset

```

## MCP server setup

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