# EURES Cross-Border Job Search & Vacancy Lookup (`vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup`) Actor

Search EURES's cross-border EEA job vacancy index by keyword, country, region, sector, contract type, education level and more, or fetch full detail - salary, benefits, contacts - for specific vacancy IDs.

- **URL**: https://apify.com/vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

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

## EURES Cross-Border Job Search & Vacancy Lookup

EURES is the European Union's official portal for cross-border employment, aggregating job vacancies posted by national employment services across every EU member state plus Iceland, Liechtenstein, Norway and Switzerland. This actor searches that live vacancy index by keyword and more than a dozen filters, or pulls full detail — salary, benefits, contact info, application link — for specific vacancy IDs you've already found.

### What this actor does

- **Two modes**: `search` (keyword + filters over the whole index) and `byIds` (full detail for vacancy IDs you supply)
- **Geographic filtering** at two levels: 31 EEA country codes, and finer-grained EU NUTS region codes that can be combined with country filters
- **More than a dozen filters**: business sector (NACE), contract type, work schedule, education level, required experience, required languages, ESCO occupation/skill codes, advertised benefits, and minimum open-post count
- **Detail-mode enrichment**: application links and deadlines, salary figures, named benefits, remote-work and travel flags, and recruiter contact details when the employer discloses them
- **Empty fields are omitted** — a listing only carries the fields EURES actually published for it

### Output per job vacancy

- `jobId` — EURES vacancy identifier, usable with `mode=byIds`
- `title`, `description` — job title and full description text
- `publicationDate`, `lastModifiedDate` — when first posted and when EURES's index last synced it
- `reference`, `documentId` — the source employment service's own reference/document numbers
- `numberOfPosts` — how many open posts this single vacancy covers
- `euresFlag` — whether the employer explicitly welcomes cross-border EEA candidates
- `countries[]`, `countryNames[]` — job location country code(s) and name(s)
- `nutsRegionCodes[]` — EU NUTS statistical region code(s) covering the job location, feedable back into the `regionCodes` input
- `locations[]`, `postalCodes[]` — location names and postal codes (`mode=byIds`)
- `positionOfferingCode` — contract type (e.g. `directhire`, `temporary`, `internship`)
- `positionScheduleCodes[]` — `fulltime` / `parttime` / `flextime`
- `employerName`, `employerWebsite`, `employerDescription`, `employerSectorCodes[]` — employer identity and NACE sector(s)
- `employerLegalId`, `employerSizeCode` — employer registration ID and organisation-size band, when disclosed (`mode=byIds`)
- `occupationUris[]` — ESCO occupation classification URIs
- `requiredSkills[]` — ESCO skill URIs required for the role (`mode=byIds`)
- `requiredYearsOfExperience`, `requiredExperienceDescription` — numeric or free-text experience requirement
- `requiredEducationLevelCode` — ISCED-based required education level
- `availableLanguages[]` — language(s) the listing is available in (`mode=search`)
- `workingLanguages[]`, `requiredLanguageSkills[]` — working language(s) and per-language proficiency requirements (`mode=byIds`)
- `drivingLicensesRequired[]` — required driving license categories, when specified
- `employmentPeriod`, `employmentStartDate`, `employmentEndDate` — contract duration and dates, when fixed-term
- `applicationUrl`, `applicationInstructions`, `applicationDeadline` — how and by when to apply (`mode=byIds`)
- `remoteWorkAllowed`, `immediateStart` — flags the employer explicitly set, when disclosed
- `travelRequired`, `travelPercentage`, `travelDescription` — travel expectations, when the employer specified them
- `salaryMin`, `salaryMax`, `salaryReference`, `salaryCurrency`, `salaryPeriod`, `salaryDescription` — pay figures and notes, only when the employer discloses pay
- `benefits[]`, `benefitsDescription` — named extra benefits (accommodation, meals, relocation, insurance types, etc.) and free-text perks, when disclosed
- `contactName`, `contactEmail`, `contactPhone`, `contactAddress` — recruiter contact details, when published (`mode=byIds`)
- `contentLanguage` — the language the returned `title`/`description` text is actually written in
- `source`, `sourceUrl` — originating employment service and the canonical EURES vacancy page URL
- `scrapedAt` — ISO 8601 timestamp of the run

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` or `byIds` |
| `searchQuery` | string | `developer` | Free-text keyword (mode=search) |
| `searchIn` | string | `EVERYWHERE` | `EVERYWHERE` / `TITLE` / `DESCRIPTION` / `EMPLOYER` — where the keyword is matched |
| `jobIds` | array | – | Vacancy IDs to fetch (mode=byIds) |
| `countries` | array | – | One or more of the 31 EEA country codes |
| `regionCodes` | array | – | EU NUTS region codes; combines with `countries` as a union |
| `sectors` | array | – | NACE Rev.2 business sector codes |
| `positionOfferingCodes` | array | – | Contract types (direct hire, temporary, internship, etc.) |
| `positionScheduleCodes` | array | – | `fulltime` / `parttime` / `flextime` |
| `educationLevels` | array | – | Required education level (basic to doctoral) |
| `experienceLevels` | array | – | Required-experience band |
| `languageSkills` | array | – | Required working language(s) |
| `occupationUris` | array | – | ESCO occupation URIs (from a prior result's `occupationUris`) |
| `skillUris` | array | – | ESCO skill URIs (from a prior `byIds` result's `requiredSkills`) |
| `benefitCodes` | array | – | Advertised extra-benefit codes |
| `euresFlagOnly` | boolean | `false` | Only cross-border-flagged vacancies |
| `publicationPeriod` | string | \`\` (any time) | `LAST_DAY` / `LAST_THREE_DAYS` / `LAST_WEEK` / `LAST_MONTH` |
| `minNumberOfPosts` | integer | – | Only vacancies with at least this many open posts |
| `sortBy` | string | `BEST_MATCH` | `BEST_MATCH` or `MOST_RECENT` (keyword searches always sort by relevance) |
| `maxItems` | integer | `50` | Hard cap on returned records (1–2000) |

#### Example: keyword search in one country

```json
{
  "mode": "search",
  "searchQuery": "warehouse",
  "countries": ["de"],
  "maxItems": 100
}
```

#### Example: bulk-hiring full-time roles in a region, posted recently

```json
{
  "mode": "search",
  "searchQuery": "",
  "regionCodes": ["deb"],
  "positionScheduleCodes": ["fulltime"],
  "minNumberOfPosts": 5,
  "publicationPeriod": "LAST_WEEK",
  "maxItems": 200
}
```

#### Example: full detail for known vacancy IDs

```json
{
  "mode": "byIds",
  "jobIds": ["MzQwNDYwIDU"]
}
```

#### Example: nurse roles requiring specific experience and languages

```json
{
  "mode": "search",
  "searchQuery": "nurse",
  "sectors": ["q"],
  "experienceLevels": ["between_1_and_2_years"],
  "languageSkills": ["de", "en"],
  "maxItems": 150
}
```

### Use cases

- **Cross-border recruitment agencies** — source candidates by sector, language and region across the EEA in one search
- **Labour-market research** — track vacancy volume and contract-type mix by country or NACE sector over time
- **HR tech integrations** — feed EURES vacancies into a job-aggregator or ATS pipeline by ESCO occupation
- **Relocation and mobility platforms** — filter for EURES-flagged jobs that explicitly welcome candidates relocating from another EEA country
- **Public-policy and academic research** — analyse posted salary, benefit and experience requirements across the single market

### FAQ

**Do I need an account or API key for EURES?**
No. EURES's job search is public; this actor queries the same public search index that powers the EURES website.

**How large is the EURES vacancy index?**
It typically holds well over a million active postings aggregated from national employment services across 31 EEA countries at any given time. Use filters and `maxItems` to target a workable slice.

**What's the difference between `search` and `byIds`?**
`search` runs a keyword/filter query and returns a page of matching vacancies with the fields EURES's listing index exposes. `byIds` fetches the full detail page for specific vacancy IDs — collect `jobId` values from a `search` run first, then feed them into a `byIds` run to get salary, benefits, contacts and the application link.

**Why do some records have far fewer fields than others?**
EURES aggregates postings from dozens of national employment services, each publishing a different level of detail. A field like `salaryMin` or `contactEmail` only appears when the originating service actually disclosed it — there's no fallback value.

**Can I filter below the country level?**
Yes — `regionCodes` accepts EU NUTS region codes (e.g. `deb` for Berlin), which you can find in the `nutsRegionCodes` field of any prior result. It combines with `countries` as a union, not an intersection.

**What does `sortBy=MOST_RECENT` actually sort on?**
It sorts by `lastModifiedDate`, the timestamp of the vacancy's last sync into EURES's index — not always the same as `publicationDate`, since a national service occasionally re-syncs an unchanged listing. This sort order is ignored whenever `searchQuery` is set, because keyword matches are always ranked by relevance.

**Will every vacancy include salary or benefits?**
No. Most EURES postings don't disclose pay or extra benefits at all. Setting `benefitCodes` narrows results to only vacancies that explicitly advertise one of the benefits you choose.

**Is this affiliated with EURES or the European Union?**
No. This is an independent, third-party actor built against EURES's own public job-search index; it is not operated by or affiliated with EURES or the European Commission.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

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

Free-text keyword to search for (mode=search). Matches job title, description and employer name depending on `searchIn`.

## `searchIn` (type: `string`):

Where the search query is matched.

## `jobIds` (type: `array`):

EURES job vacancy IDs, as found in the `id` field of search results or in a job's detail URL, e.g. `MzQwNDYwIDU`.

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

Restrict results to job locations in these countries. Leave empty for all EEA countries.

## `regionCodes` (type: `array`):

Restrict results to job locations in these EU NUTS region codes (finer-grained than `countries`), e.g. `deb` for Berlin (Germany) or `no0b` for Trondelag (Norway). Find a region's code in the `nutsRegionCodes` output field of a previous run, or on the EURES advanced-search location picker. Combines with `countries` as an OR (union of matches).

## `sectors` (type: `array`):

Restrict results to these NACE Rev.2 business sectors.

## `positionOfferingCodes` (type: `array`):

Restrict results to these contract/position offering types.

## `positionScheduleCodes` (type: `array`):

Restrict results to these work schedules.

## `educationLevels` (type: `array`):

Restrict results to these required education levels.

## `experienceLevels` (type: `array`):

Restrict results to these required-experience bands.

## `languageSkills` (type: `array`):

Restrict results to jobs requiring at least basic proficiency in these languages.

## `occupationUris` (type: `array`):

Restrict results to jobs classified under these ESCO occupation URIs. Copy values from the `occupationUris` field of a previous search result, e.g. `http://data.europa.eu/esco/occupation/f2b15a0e-e65a-438a-affb-29b9d50b77d1`.

## `skillUris` (type: `array`):

Restrict results to jobs requiring these ESCO skill URIs. Copy values from the `requiredSkills` field of a previous `mode=byIds` result, e.g. `http://data.europa.eu/esco/skill/ccd0a1d9-afda-43d9-b901-96344886e14d`.

## `benefitCodes` (type: `array`):

Restrict results to jobs that explicitly advertise these extra (non-salary) benefits. Note: most EURES listings do not disclose extra-benefit information at all, so this filter narrows results significantly -- leave empty to include all jobs regardless of disclosed benefits.

## `euresFlagOnly` (type: `boolean`):

Only return jobs explicitly flagged as cross-border EURES vacancies (employer welcomes candidates from other EEA countries).

## `publicationPeriod` (type: `string`):

Only return jobs published within this time window.

## `minNumberOfPosts` (type: `integer`):

Only return job vacancies offering at least this many open posts/positions (useful for finding bulk-hiring vacancies).

## `sortBy` (type: `string`):

Order of returned results. `MOST_RECENT` orders by each listing's last-synced/last-modified timestamp in EURES's own index (output field `lastModifiedDate`), which usually but not always matches `publicationDate` -- national employment services periodically re-sync unchanged listings, which refreshes this timestamp without a new posting. Note: when `searchQuery` is set, results are always ordered by relevance (best match) regardless of this setting, since EURES cannot reliably combine keyword search with most-recent ordering.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "developer",
  "searchIn": "EVERYWHERE",
  "jobIds": [],
  "countries": [],
  "regionCodes": [],
  "sectors": [],
  "positionOfferingCodes": [],
  "positionScheduleCodes": [],
  "educationLevels": [],
  "experienceLevels": [],
  "languageSkills": [],
  "occupationUris": [],
  "skillUris": [],
  "benefitCodes": [],
  "euresFlagOnly": false,
  "publicationPeriod": "",
  "sortBy": "BEST_MATCH",
  "maxItems": 50
}
```

# Actor output Schema

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

Dataset containing all scraped EURES job vacancies.

# 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 = {
    "mode": "search",
    "searchQuery": "developer",
    "searchIn": "EVERYWHERE",
    "jobIds": [],
    "countries": [],
    "regionCodes": [],
    "sectors": [],
    "positionOfferingCodes": [],
    "positionScheduleCodes": [],
    "educationLevels": [],
    "experienceLevels": [],
    "languageSkills": [],
    "occupationUris": [],
    "skillUris": [],
    "benefitCodes": [],
    "euresFlagOnly": false,
    "publicationPeriod": "",
    "sortBy": "BEST_MATCH",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup").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 = {
    "mode": "search",
    "searchQuery": "developer",
    "searchIn": "EVERYWHERE",
    "jobIds": [],
    "countries": [],
    "regionCodes": [],
    "sectors": [],
    "positionOfferingCodes": [],
    "positionScheduleCodes": [],
    "educationLevels": [],
    "experienceLevels": [],
    "languageSkills": [],
    "occupationUris": [],
    "skillUris": [],
    "benefitCodes": [],
    "euresFlagOnly": False,
    "publicationPeriod": "",
    "sortBy": "BEST_MATCH",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup").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 '{
  "mode": "search",
  "searchQuery": "developer",
  "searchIn": "EVERYWHERE",
  "jobIds": [],
  "countries": [],
  "regionCodes": [],
  "sectors": [],
  "positionOfferingCodes": [],
  "positionScheduleCodes": [],
  "educationLevels": [],
  "experienceLevels": [],
  "languageSkills": [],
  "occupationUris": [],
  "skillUris": [],
  "benefitCodes": [],
  "euresFlagOnly": false,
  "publicationPeriod": "",
  "sortBy": "BEST_MATCH",
  "maxItems": 50
}' |
apify call vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/eures-cross-border-job-search-and-vacancy-lookup"
        }
    }
}
```

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/6jUhhkfjsSlsGsgzy/builds/dzJqsz5Efxce2MhBl/openapi.json
