# SEPE Spain Jobs Scraper (Empleate.gob.es) (`santamaria-automations/sepe-es-scraper`) Actor

Extract job listings from Spain's national public employment service (SEPE) via empleate.gob.es. Returns title, company, location, autonomous community, employment type, salary, full description and contact details. Covers all 17 comunidades autonomas plus Ceuta and Melilla.

- **URL**: https://apify.com/santamaria-automations/sepe-es-scraper.md
- **Developed by:** [NanoScrape](https://apify.com/santamaria-automations) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 33.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

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

## SEPE.es Scraper: Spain National Employment Service Jobs (Empleate)

Extract job listings from **empleate.gob.es**, the official portal of Spain's **national public employment service**
(Servicio Publico de Empleo Estatal, SEPE). Returns structured job data including title, company, location,
autonomous community, province, employment type, salary, GPS coordinates, vacancies, education requirements and description.

Covers all **17 autonomous communities plus Ceuta and Melilla** - every job posted on the SEPE national platform.
Regional services (LANBIDE Basque Country, SOC Catalonia, etc.) also contribute listings via the national aggregator.

***

### What It Does

- Searches empleate.gob.es for any keyword in Spanish
- Extracts all listing fields: title, company, city, province, autonomous community, employment type, salary, description
- Maps Spanish employment types (jornada completa, jornada parcial, contrato indefinido, temporal, practicas)
- Maps locations to one of 19 Spanish regions (17 comunidades autonomas + Ceuta + Melilla)
- Extracts CNO occupation codes and SEPE sector codes
- Returns GPS coordinates (latitude/longitude) for each listing when available
- Captures vacancies count, disability accessible flag, seniority level, education and experience requirements
- Handles SEPE-specific features: public employment, disability-inclusive listings, interregional postings
- Returns data instantly - no browser, no JavaScript, plain HTTP against the SEPE Solr API

***

### Company Name Note

SEPE aggregates listings from many sources. Only partner-aggregated listings (from TecnoEmpleo, InfoJobs, HacesFalta and similar platforms) carry a named employer in `company_name`. **Listings posted directly by public employment offices — which account for a large share of SEPE postings — have no employer name by design.** For those listings, `company_name` is null and that is the correct, expected value. Descriptions often contain the hiring organization name in plain text even when the structured field is null.

***

### Sample Output

```json
{
  "_type": "job",
  "id": "1857143652",
  "title": "Ingeniero/a de Automatizacion Junior, Valencia",
  "job_url": "https://www.empleate.gob.es/empleo/#/oferta/ingeniero-a-de-automatizacion-junior-valencia/1857143652",
  "source_url": "https://www.empleate.gob.es/empleo/#/oferta/ingeniero-a-de-automatizacion-junior-valencia/1857143652",
  "source_platform": "empleate.gob.es",
  "company_name": "Michael Page",
  "company_website": null,
  "company_logo_url": "https://www.empleate.gob.es/empleo/resources/images/companies/TECNO_EMPLEO.png",
  "location": "Valencia",
  "country": "ES",
  "region": "Comunidad Valenciana",
  "province": "Valencia",
  "posted_at_text": "31 ago. 2026",
  "posted_at_datetime": "2026-08-31T10:51:49Z",
  "employment_type": "permanent",
  "workplace_type": "on-site",
  "salary_min": null,
  "salary_max": null,
  "salary_currency": null,
  "salary_period": null,
  "salary_text": null,
  "description": "Ingeniero/a de Automatizacion Junior Las principales funciones que desarrollaras seran...",
  "description_full": "Ingeniero/a de Automatizacion Junior ...",
  "description_html": "Ingeniero/a de Automatizacion Junior ...",
  "description_md": "Ingeniero/a de Automatizacion Junior ...",
  "contact_emails": [],
  "contact_phones": [],
  "contact_urls": ["https://www.tecnoempleo.com/..."],
  "apply_url": "https://www.tecnoempleo.com/...",
  "search_query": "ingeniero",
  "scraped_at": "2026-08-31T12:00:00Z",
  "cno_code": "2461",
  "community_code": "10",
  "sector_code": null,
  "category": "INGENIERIA/CALIDAD/CIENCIAS",
  "subcategory": "INGENIERIAS",
  "vacancies": 1,
  "disability_accessible": false,
  "modality_code": "0",
  "source_origin": "TECNO_EMPLEO",
  "latitude": 39.4699075,
  "longitude": -0.3762881,
  "num_applicants": null,
  "seniority_level": null,
  "education_required": null,
  "experience_required": null,
  "start_date": null,
  "contract_type_raw": "Indefinido",
  "horario": "Jornada completa"
}
```

***

### Pricing

| Event | When triggered | Price |
|-------|----------------|-------|
| `actor-start` | Once per run | $0.001 |
| `job-serp-result` | Per job returned (SERP only mode) | $0.003 |
| `job-detail-result` | Per job returned (with detail fetch) | $0.005 |

**Example costs:**

- 100 jobs (SERP only): $0.001 + 100 x $0.003 = $0.31
- 100 jobs (with details): $0.001 + 100 x $0.005 = $0.51
- 1000 jobs (SERP only): $0.001 + 1000 x $0.003 = $3.00

***

### Input Fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `searchQueries` | array | - | Keywords in Spanish (e.g. "programador", "enfermero", "ingeniero", "contable", "conductor") |
| `location` | string | - | Spanish province or city filter (e.g. "Madrid", "Barcelona", "Sevilla", "Valencia") |
| `searchUrls` | array | - | Paste empleate.gob.es search URLs directly |
| `maxResults` | integer | 100 | Total result cap across all queries |
| `maxResultsPerQuery` | integer | 100 | Cap per keyword or URL |
| `includeJobDetails` | boolean | true | Include full description (always populated from SEPE API) |
| `includeCompanyDetails` | boolean | false | Attempt to extract company website |
| `maxConcurrency` | integer | 5 | Concurrent requests (1-20) |

***

### Output Fields

| Field | Description |
|-------|-------------|
| `_type` | Always "job" |
| `id` | SEPE vacancy ID |
| `title` | Job title |
| `job_url` | Canonical vacancy URL on empleate.gob.es |
| `source_platform` | Always "empleate.gob.es" |
| `company_name` | Employer name. Null for direct SEPE/public-office listings (see Company Name Note above) |
| `company_website` | Employer website (when listed) |
| `company_logo_url` | Logo of the partner source system (HACESFALTA, INSERTIA, LABORA, LANBIDE, PORTALENTO, WEB, SOC, etc.). URL format: `https://www.empleate.gob.es/empleo/resources/images/companies/{ORIGEN}.png`. Null when origen is absent. |
| `location` | City or municipality |
| `country` | Always "ES" |
| `region` | Spanish autonomous community: Madrid, Cataluna, Andalucia, Comunidad Valenciana, Pais Vasco, etc. |
| `province` | Spanish province name (e.g. "Barcelona", "A Coruña", "Valencia") |
| `posted_at_text` | Spanish date format: "25 ago. 2026" (date-only — SEPE does not publish listing times) |
| `posted_at_datetime` | ISO 8601 UTC full timestamp from when listing entered SEPE system |
| `employment_type` | permanent / part-time / temporary / flexible |
| `workplace_type` | on-site / hybrid / remote |
| `salary_min` | Minimum salary in EUR |
| `salary_max` | Maximum salary in EUR |
| `salary_currency` | Always "EUR" when salary present |
| `salary_period` | month / year |
| `salary_text` | Salary as displayed |
| `description` | Job description snippet (500 chars) |
| `description_full` | Full plain-text description |
| `description_html` | Full HTML description |
| `description_md` | Full Markdown description |
| `contact_emails` | Email addresses extracted from description |
| `contact_phones` | Spanish phone numbers extracted from description |
| `contact_urls` | External URLs extracted from description |
| `apply_url` | Application URL (partner site URL when available, otherwise job\_url) |
| `cno_code` | CNO occupation code (Clasificacion Nacional de Ocupaciones) |
| `community_code` | SEPE autonomous community code (01-19) |
| `sector_code` | SEPE sector code |
| `category` | Job category (e.g. INFORMATICA/TELECOMUNICACIONES) |
| `subcategory` | Job sub-category (e.g. INGENIERIAS) |
| `vacancies` | Number of open positions |
| `disability_accessible` | true if the listing is accessible or targeted at workers with disabilities |
| `modality_code` | SEPE modality: 0=presencial, 1=remoto, 2=hibrido |
| `source_origin` | Source system feeding SEPE (TECNO\_EMPLEO, HACESFALTA, INFOJOBS, etc.) |
| `latitude` | GPS latitude (decimal degrees) |
| `longitude` | GPS longitude (decimal degrees) |
| `num_applicants` | Number of applicants when available |
| `seniority_level` | Seniority level (e.g. "Mando intermedio") |
| `education_required` | Education level required |
| `experience_required` | Experience requirement text |
| `start_date` | Expected start date ISO 8601 UTC (when provided) |
| `contract_type_raw` | Raw contract type text from SEPE (e.g. "Indefinido", "Temporal") |
| `horario` | Human-readable schedule (e.g. "Jornada completa") |
| `search_query` | Query that returned this result |
| `scraped_at` | ISO 8601 UTC scrape timestamp |

***

### Use with AI Agents (MCP)

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server"],
      "env": { "APIFY_TOKEN": "your_token" }
    }
  }
}
```

Then ask your AI: "Search SEPE for software developer jobs in Barcelona and return the results as JSON."

***

### Why This Scraper

- **Official government data**: SEPE is Spain's national public employment service. All listings are government-verified
- **HTTP-only Go**: No browser, no Playwright, no Puppeteer. Fast, cheap, reliable
- **Full national coverage**: All 17 comunidades autonomas plus Ceuta and Melilla, via the SEPE national aggregator
- **Rich structured data**: CNO occupation codes, sector codes, GPS coordinates, vacancies count and autonomous community classification
- **Spanish salary conventions**: Handles both monthly (mensual) and annual (anual) salary formats in EUR
- **Disability-inclusive listings**: SEPE marks listings with disability accessibility requirements

***

### Common Use Cases

- **Market research**: Track job postings by region, sector or occupation code across all of Spain
- **Salary benchmarking**: Identify salary ranges for Spanish roles by region and sector
- **Public sector jobs**: SEPE lists government, education and healthcare vacancies
- **Labour market analytics**: Analyze employment trends across Spanish autonomous communities
- **Talent pipeline**: Monitor which companies are hiring in specific Spanish regions
- **Geo analysis**: Use latitude/longitude to plot hiring density across Spanish territory
- **Apprenticeship tracking**: Monitor formacion profesional and practicas opportunities by sector

***

### Notes and Limits

- **Coverage**: National SEPE plus regional PES contributions (LANBIDE, SOC, INAEM, SEXPE, SAE, etc.)
- **Language**: All listings are in Spanish (es-ES). Catalan, Basque and Galician variants occasionally appear in regional listings
- **Pagination**: SEPE Solr API returns up to 50 results per page; actor paginates automatically
- **Salary data**: Many Spanish salaries are listed as "segun convenio" (per collective agreement) which maps to null
- **Company name**: Null on direct SEPE / public employment office listings — this is expected, not a data quality issue. Only partner-sourced listings carry employer names
- **Listing expiry**: SEPE listings can expire within 48 hours to 7 days. Run regularly to capture current listings
- **Job URLs**: The empleate.gob.es URL is an Angular SPA that always returns HTTP 200 regardless of listing status. Use apply\_url (the originating partner URL) to verify if a listing is still live
- **Employment types**: jornada completa (full-time), jornada parcial (part-time), contrato indefinido (permanent), temporal (temporary), practicas (internship), contrato de formacion (apprenticeship)
- **Update frequency**: SEPE listings are updated daily. Run daily for fresh data
- **Regional services**: LANBIDE (Basque), SOC (Catalan), INAEM (Aragonese), SEPECAM (Castilian), SAE (Andalusian) and SEXPE (Extremaduran) listings are all included via the national aggregator
- **Scope**: This actor covers the NATIONAL SEPE system only. Individual regional portals with non-shared listings are out of scope

***

### Related Actors

- [Job Feed Aggregator](https://apify.com/nanoscrape/job-feed) - Multi-country job aggregator including Spain
- [Career Site Jobs Scraper](https://apify.com/nanoscrape/career-site-jobs-scraper) - Scrape any company careers page
- [Website Job Extractor](https://apify.com/nanoscrape/website-job-extractor) - Extract jobs from any website
- [Indeed Scraper](https://apify.com/nanoscrape/indeed-scraper) - Global jobs including Spain
- [InfoJobs Scraper](https://apify.com/nanoscrape/infojobs-scraper) - Spain's top commercial job board
- [VDAB.be Scraper](https://apify.com/nanoscrape/vdab-be-scraper) - Belgium Flanders public employment service
- [Forem.be Scraper](https://apify.com/nanoscrape/forem-be-scraper) - Belgium Wallonia public employment service

***

### Support

Issues or questions? Open a ticket on the [Issues tab](https://console.apify.com/actors/issues) or email contact@nanoscrape.com.

# Actor input Schema

## `searchQueries` (type: `array`):

One or more keyword queries in Spanish (for example 'programador', 'enfermero', 'ingeniero', 'administrativo', 'conductor'). Each runs as a separate search. Results are deduplicated.

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

Spanish province or city to filter by (for example 'Madrid', 'Barcelona', 'Sevilla', 'Valencia', 'Bilbao'). Applied to all keyword searches.

## `searchUrls` (type: `array`):

Paste one or more empleate.gob.es search URLs. Go to empleate.gob.es, run a search, and copy the URL from the browser address bar.

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

Total cap across all queries and URLs.

## `maxResultsPerQuery` (type: `integer`):

Maximum results per search URL or keyword.

## `includeJobDetails` (type: `boolean`):

When true, includes full description from each listing. For SEPE, full description is available directly from the search API so this is always populated.

## `includeCompanyDetails` (type: `boolean`):

Also attempt to extract company website from the job listing.

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

Maximum concurrent requests. Only used when fetching detail pages.

## Actor input object example

```json
{
  "searchQueries": [
    "ingeniero"
  ],
  "location": "Madrid",
  "maxResults": 10,
  "maxResultsPerQuery": 10,
  "includeJobDetails": true,
  "includeCompanyDetails": false,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `jobListings` (type: `string`):

Dataset of Spanish job listings from SEPE (empleate.gob.es). Each row has: \_type, id, title, job\_url, source\_url, source\_platform, company\_name (null for public employment office listings — many SEPE listings are anonymous by design), company\_website, company\_logo\_url (partner source logo URL; constructed from origen field; all SEPE origen values have a valid PNG), location (city), province, country (ES), region (autonomous community), salary\_min, salary\_max, salary\_currency (EUR), salary\_period, salary\_text, employment\_type, workplace\_type (on-site/hybrid/remote), description, description\_full, description\_html, description\_md, contact\_emails, contact\_phones, contact\_urls, apply\_url, search\_query, scraped\_at, cno\_code, community\_code, sector\_code, category, subcategory, vacancies, disability\_accessible, modality\_code, source\_origin, latitude, longitude, num\_applicants, seniority\_level, education\_required, experience\_required, start\_date, contract\_type\_raw, horario.

# 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 = {
    "searchQueries": [
        "ingeniero"
    ],
    "location": "Madrid",
    "maxResults": 10,
    "maxResultsPerQuery": 10,
    "includeJobDetails": false,
    "maxConcurrency": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("santamaria-automations/sepe-es-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 = {
    "searchQueries": ["ingeniero"],
    "location": "Madrid",
    "maxResults": 10,
    "maxResultsPerQuery": 10,
    "includeJobDetails": False,
    "maxConcurrency": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("santamaria-automations/sepe-es-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 '{
  "searchQueries": [
    "ingeniero"
  ],
  "location": "Madrid",
  "maxResults": 10,
  "maxResultsPerQuery": 10,
  "includeJobDetails": false,
  "maxConcurrency": 5
}' |
apify call santamaria-automations/sepe-es-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,santamaria-automations/sepe-es-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/jVnJkhfjqeVq7SESa/builds/ieGqbB4pv0lTU8zQa/openapi.json
