# Licitaciones Junta de Andalucía | Contratación Pública (`jesusarsan/licitaciones-junta-andalucia`) Actor

Extrae licitaciones, contratos menores y adjudicaciones de la Junta de Andalucía. Más de 912.000 expedientes de 553 organismos y 8 provincias, con importes, adjudicatarios, fechas y enlaces. Spanish public procurement / tenders dataset for Andalusia.

- **URL**: https://apify.com/jesusarsan/licitaciones-junta-andalucia.md
- **Developed by:** [Jesus Arteaga](https://apify.com/jesusarsan) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / 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?

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

## Licitaciones y Contratación Pública — Junta de Andalucía

**Todos los contratos que publica la Junta de Andalucía, en una tabla que puedes descargar.**
*Every contract published by the Andalusian regional government, as a table you can download.*

***

### Español

Son más de **912.000 expedientes**, y suben cada día. Obras, servicios, suministros y contratos menores de **553 organismos** públicos andaluces. El más antiguo es de mayo de 2008 y el más reciente se publicó esta misma mañana.

De cada expediente sale el objeto del contrato, el importe de licitación, el estado, la provincia, el organismo que lo convocó, quién se lo llevó, con qué NIF y por cuánto dinero. **51 columnas**, ya limpias: los importes vienen como número, las fechas en formato ISO y los códigos traducidos, así que no verás un `18` donde debería poner Granada.

**Para quién es útil**

Si te presentas a concursos públicos, aquí ves a qué precios se está adjudicando lo que tú haces y qué empresas te están ganando. Si analizas gasto público o haces periodismo de datos, tienes el histórico entero sin pelearte con el buscador del portal.

**Qué lo diferencia**

El portal de la Junta no entrega más de **10.000 registros por consulta**, da igual lo que diga el contador. Este Actor te trae los 912.000 completos, comprobado contra el recuento del propio portal: **100% de cobertura y cero duplicados**. Una extracción entera tarda unos minutos.

Los filtros se aplican en el servidor. Si solo quieres las obras de Sevilla, son 3.850 registros en unos segundos y pagas por esos, no por el corpus entero.

Una advertencia honesta: el 90% del volumen son **contratos menores**, que es donde de verdad está el detalle del gasto ordinario. Si buscabas solo las grandes licitaciones abiertas, filtra por procedimiento y te ahorras la mayor parte.

***

### English

Over **912,000 records**, and more every day. Public works, services, supplies and small contracts from **553 public bodies** across Andalusia, Spain. The oldest goes back to May 2008, the newest went up this morning.

For each one you get what was contracted, the tender value, its status, the province, the awarding body, who won it, their tax ID and how much they were paid. **51 columns**, already cleaned up: amounts come through as numbers, dates in ISO format, and codes resolved to names, so you won't find an `18` where it should say Granada.

**Who it's for**

If you bid for public contracts, this shows you what work like yours is going for and which companies keep winning it. If you research public spending or do data journalism, it's the complete history without fighting the government's own search tool.

**What sets it apart**

The portal won't hand over more than **10,000 records per query**, whatever the result counter claims. This Actor gets you all 912,000, checked against the portal's own count: **100% coverage, zero duplicates**. A full extraction takes a few minutes.

Filtering happens server-side. If you only want construction work in Seville, that's 3,850 records in a few seconds, and you pay for those rather than the whole corpus.

One honest caveat: 90% of the volume is **minor contracts**, which is where the day-to-day spending detail actually lives. If you only wanted the large open tenders, filter by procedure and you'll skip most of it.

***

### Columnas / Output fields

| Grupo / Group | Campos / Fields |
|---|---|
| Identificación / Identification | id\_documento, id\_expediente, numero\_expediente, titulo, url\_ficha |
| Clasificación / Classification | tipo\_contrato, procedimiento, estado, tramitacion, forma\_presentacion, sistema\_racionalizacion, codigos\_cpv |
| Organismo / Awarding body | perfil\_contratante, perfil\_contratante\_codigo, perfil\_contratante\_dir3, provincias |
| Importes / Amounts | importe\_licitacion, valor\_estimado, importe\_adjudicacion |
| Adjudicación / Award | adjudicatario, nif\_adjudicatario, numero\_contrato, fecha\_formalizacion, fecha\_resolucion, adjudicacion\_definitiva, num\_adjudicaciones |
| Fechas / Dates | fecha\_publicacion, fecha\_limite\_presentacion |
| Cláusulas / Clauses | clausulas\_sociales, clausulas\_ambientales, tiene\_clausulas\_sociales, tiene\_clausulas\_ambientales |
| Financiación / Funding | cofinanciado\_ue, origenes\_cofinanciacion |
| Trazabilidad / Traceability | extraido\_en, adjudicaciones\_raw, lotes\_raw |

Cada columna de código va acompañada de su etiqueta legible. El portal devuelve el procedimiento como `"9"` y la provincia como `["23"]`; aquí salen además como **Menor** y **Jaén**.

**Ojo con la clave única:** es `id_documento`, no `id_expediente`. El portal reutiliza valores de `idExpediente` entre expedientes distintos, y deduplicar por ese campo tira alrededor del 2% de los registros.

*Note on the unique key: use `id_documento`, not `id_expediente`. The portal reuses `idExpediente` values across genuinely different records, so deduplicating on it silently drops around 2% of the dataset.*

***

### Ejemplos / Examples

```jsonc
// Prueba rápida / Quick test
{ "maxResultados": 1000 }

// Obras en Sevilla / Construction work in Seville
{ "tipoContrato": "OBRA", "provincia": "41", "maxResultados": 0 }

// Solo lo abierto a presentación / Only what's still open for bids
{ "estado": "PUB", "maxResultados": 0 }

// Un organismo entero / A single public body
{ "perfilContratante": "COED02", "maxResultados": 0 }

// Todo / Everything
{ "maxResultados": 0, "concurrencia": 6 }
```

Si una ejecución se corta o te quedas sin presupuesto, relánzala con `{"reanudar": true}`: retoma donde lo dejó, sin repetir ni perder registros.

*If a run stops early or you hit your spending limit, restart it with `{"reanudar": true}`. It picks up exactly where it left off, with nothing repeated and nothing lost.*

***

### Legal

Los datos son **públicos y reutilizables**: la contratación pública debe publicarse por ley (LCSP 9/2017) y está cubierta por la [licencia de reutilización de datos.gob.es](https://datos.gob.es/es/aviso-legal).

Este dataset incluye `adjudicatario` y `nif_adjudicatario`. Cuando el adjudicatario es una persona física y no una empresa, eso es **dato personal sujeto al RGPD**. Si vas a redistribuir el dataset, documenta tu base jurídica de tratamiento.

*The data is public and reusable under Spanish public procurement law. Note that award recipient names and tax IDs can be personal data under GDPR when the contractor is an individual rather than a company. Document your lawful basis before redistributing.*

Este Actor no está afiliado a la Junta de Andalucía ni cuenta con su respaldo.
*This Actor is not affiliated with or endorsed by the Junta de Andalucía.*

# Actor input Schema

## `maxResultados` (type: `integer`):

0 = sin límite (~912.000 registros, unos 8-10 minutos). Empieza con 1000 para probar.

## `provincia` (type: `string`):

Vacío = todas. Solo un tercio de los expedientes declara provincia; los demás se incluyen únicamente si dejas este campo vacío.

## `tipoContrato` (type: `string`):

Vacío = todos.

## `procedimiento` (type: `string`):

Vacío = todos. Los contratos menores son la mayor parte del volumen. La lista es la del propio portal, así que algún procedimiento poco habitual puede no tener todavía ningún expediente.

## `estado` (type: `string`):

Vacío = todos. "Publicada" son los que siguen abiertos a presentación.

## `perfilContratante` (type: `string`):

Código del organismo. Ej: SYBS03 = Servicio Andaluz de Salud, COED02 = Agencia Pública Andaluza de Educación. Vacío = los 553 organismos. La lista completa sale en la columna perfil\_contratante\_codigo del dataset.

## `tramitacion` (type: `string`):

Vacío = todas.

## `formaPresentacion` (type: `string`):

Vacío = todas.

## `concurrencia` (type: `integer`):

Subirlo acelera pero aumenta el riesgo de 429. 4 es un valor seguro y ya alcanza unos 2.800 registros/s.

## `reanudar` (type: `boolean`):

Retoma desde el checkpoint, sin repetir los registros ya extraídos.

## `usarProxyEspana` (type: `boolean`):

Normalmente no hace falta: el portal responde bien sin proxy. Actívalo solo si ves bloqueos o errores 429 persistentes. Requiere proxy residencial en tu plan de Apify.

## Actor input object example

```json
{
  "maxResultados": 1000,
  "provincia": "",
  "tipoContrato": "",
  "procedimiento": "",
  "estado": "",
  "perfilContratante": "",
  "tramitacion": "",
  "formaPresentacion": "",
  "concurrencia": 4,
  "reanudar": false,
  "usarProxyEspana": false
}
```

# Actor output Schema

## `expedientes` (type: `string`):

Todos los expedientes extraídos, con las 51 columnas normalizadas. Abre por defecto la vista de resumen; en la consola puedes cambiar a la vista de adjudicaciones.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("jesusarsan/licitaciones-junta-andalucia").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("jesusarsan/licitaciones-junta-andalucia").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 '{}' |
apify call jesusarsan/licitaciones-junta-andalucia --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jesusarsan/licitaciones-junta-andalucia"
        }
    }
}

```

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/E6MiHp5Ah4P4rBGfM/builds/xvaSE9pA4nSvH2gB2/openapi.json
