# Aragon Public Contracts Registry Scraper (`xamto1987/aragon-tenders`) Actor

Registro de contratos publicos de la Comunidad Autonoma de Aragon (contratos mayores y menores), via el portal CKAN opendata.aragon.es. Aragon public procurement contracts registry.

- **URL**: https://apify.com/xamto1987/aragon-tenders.md
- **Developed by:** [Santi Belloso Lopez](https://apify.com/xamto1987) (community)
- **Categories:** Lead generation, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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

## Aragon Public Contracts Registry Scraper · Registro de contratos de Aragón

Extrae el **Registro de Contratos de la Comunidad Autónoma de Aragón**
(contratos mayores y contratos menores) desde el portal oficial de datos
abiertos **opendata.aragon.es** (CKAN), con filtrado en servidor.

Scrapes the **Aragon Regional Government's public contracts registry**
(major and minor contracts) from the official open-data CKAN portal, with
server-side filtering.

***

### 🇪🇸 Español

#### Qué obtienes

Un ítem por contrato del registro (mayores o menores, según `tipoRegistro`):

| Campo | Qué es |
|---|---|
| `idExpediente` | Número de expediente |
| `titulo`, `objeto` | Objeto del contrato |
| `administracion`, `organoContratacion` | Comunidad Autónoma de Aragón y órgano de contratación concreto |
| `tipoContrato`, `procedimiento`, `tramitacion` | Suministros/Servicios/Obras…, procedimiento de adjudicación |
| `estado` | Estado del expediente (`En ejecución`, `Cerrado`…) |
| `presupuestoLicitacionSinIva`/`ConIva`, `valorEstimadoContrato` | Importes **como número** |
| `importeAdjudicacionSinIva`/`ConIva` | Importe de adjudicación, como número |
| `adjudicatario.nif`, `.razonSocial`, `.tipoPersona` | Adjudicatario — ver protección de datos abajo |
| `codigosCpv`, `duracionContrato` | Clasificación económica y duración |
| `fechaPublicacionAnuncio` (=fecha de licitación), `fechaPublicacionAdjudicacion`, `fechaPublicacionFormalizacion` | Fechas clave, en ISO |
| `tipoRegistro` | `mayores` o `menores` |

#### Parámetros de entrada

| Parámetro | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `tipoRegistro` | `mayores`|`menores` | `mayores` | Qué recurso CKAN consultar |
| `keywords` | lista de textos | `[]` | Busca en TODAS las columnas de texto, en servidor (CKAN `q`). Vacío = sin filtro |
| `tipoContrato` | enum | — | `Suministros`, `Servicios`, `Obras`… (filtro exacto en servidor) |
| `ano` | texto | — | Columna `ANO` (filtro exacto en servidor); el registro cubre desde 2023 |
| `importeMinimo` / `importeMaximo` | número | — | Filtro por importe de adjudicación (o presupuesto). ⚠️ **En cliente** — ver nota técnica |
| `incluirContactosNominales` | booleano | `false` | Ver protección de datos abajo |
| `maxItems` | entero | `200` | Tope de ítems |

Ejemplo:

```json
{ "tipoRegistro": "mayores", "keywords": ["limpieza"], "tipoContrato": "Servicios", "maxItems": 100 }
```

#### El filtrado ocurre en el servidor — salvo el importe

Este actor traduce `tipoContrato`/`ano` a `filters` de CKAN (igualdad
exacta) y `keywords` a `q` (búsqueda de texto libre), ambos enviados al
servidor `datastore_search`. **Excepción documentada**: el API CKAN de
Aragón solo admite igualdad exacta en `filters`, sin operadores de rango —
por eso `importeMinimo`/`importeMaximo` se aplican en **cliente**, tras
traer cada página del servidor (mismo patrón que `soloAbiertas` en
`spain-grants-bdns`). El log de la ejecución indica claramente qué se
filtró en servidor y qué en cliente.

#### Protección de datos: nombres de personas físicas fuera por defecto

El campo `NIF ADJUDICATARIO` del registro incluye, para una parte de los
contratos, un NIF **sin enmascarar** o **enmascarado por la propia fuente**
(`"***4446**"`, igual que en BDNS) cuando el adjudicatario es una persona
física (autónomo). Con `incluirContactosNominales: false` — el valor por
defecto — si el adjudicatario no es inequívocamente una persona jurídica
(clasificación fail-closed del NIF), `adjudicatario.nif` y `.razonSocial`
se anulan y solo queda `.tipoPersona`. El resto del contrato (importe,
órgano, fechas…) se conserva: es gasto público, no dato personal.

#### Fuente y aviso legal

- **Fuente oficial**: dataset CKAN *"Registro de Contratos de la Comunidad
  Autónoma de Aragón - Desde 2023"*, portal de datos abiertos del Gobierno
  de Aragón — `https://opendata.aragon.es/api/3/action/datastore_search`.
  7.350 filas (Contratos Mayores) y 12.649 filas (Contratos Menores)
  verificadas el 23-ago-2026, actualización trimestral.
- **Licencia**: Creative Commons Attribution 4.0 (CC-BY-4.0), verificada en
  los metadatos del dataset.
- Robots.txt de `opendata.aragon.es` verificado con curl: solo prohíbe
  `/ckan/api/` (con prefijo) y `/GA_OD_Core/preview|download|views*`; el
  endpoint usado aquí, `/api/3/action/datastore_search` sin ese prefijo, no
  está prohibido.
- Este actor **solo lee datos públicos**, sin login, sin cookies y sin
  saltarse ninguna medida técnica. No es un producto oficial ni está
  afiliado, respaldado ni verificado por el Gobierno de Aragón.

***

### 🇬🇧 English

#### What it does

`aragon-tenders` scrapes the **Aragon Regional Government's contracts
registry** (major and minor contracts) from the official CKAN open-data
portal, with server-side filtering via `datastore_search`.

#### Input

See the Spanish table above — field names and defaults are identical.
`importeMinimo`/`importeMaximo` are applied **client-side**: CKAN's
`datastore_search` only supports exact-match `filters`, not range
operators — documented limitation, same pattern as `soloAbiertas` in
`spain-grants-bdns`.

#### GDPR: named individuals excluded by default

The `NIF ADJUDICATARIO` column carries an unmasked or source-masked tax ID
for sole-trader (natural person) awardees. With `incluirContactosNominales:
false` (default), `adjudicatario.nif`/`.razonSocial` are nulled unless the
awardee is unambiguously a legal entity (fail-closed NIF classification).

#### Disclaimer

Data comes from the Aragon Regional Government's official CKAN open-data
portal (`opendata.aragon.es`). This actor is **not** an official product
and is not affiliated with or endorsed by the Gobierno de Aragón. Reuse is
free under **CC-BY-4.0** (attribution required).

***

**Palabras clave / Keywords**: contratos públicos Aragón, registro de
contratos, licitaciones Aragón, contratación pública, CKAN open data,
Gobierno de Aragón, public procurement Spain, contratos menores, contratos
mayores, CPV.

# Actor input Schema

## `tipoRegistro` (type: `string`):

`mayores` = Contratos Mayores (expedientes de licitacion formal, con lotes y presupuesto de licitacion). `menores` = Contratos Menores (adjudicacion directa, sin licitacion previa). Son dos recursos CKAN distintos con columnas ligeramente distintas. / `mayores` = major contracts (formal tenders); `menores` = minor/direct-award contracts.

## `keywords` (type: `array`):

Lista de terminos a buscar en TODAS las columnas de texto del registro (busqueda de texto libre `q` de CKAN, en servidor). Cada termino se consulta por separado y los resultados se combinan (cualquiera coincide, igual que en catalonia-tenders). Vacio = sin filtro de texto. / Server-side full-text search (CKAN `q`); each keyword queried separately and merged (OR).

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

Filtra por `TIPO DE CONTRATO`, en servidor (igualdad exacta). Valores reales verificados con curl sobre una muestra de 1000 filas de Contratos Mayores. Vacio = todos. / Server-side exact-match filter; empty = all types.

## `ano` (type: `string`):

Filtra por columna `ANO`, en servidor (igualdad exacta). El registro cubre desde 2023. Vacio = todos los años disponibles. / Server-side exact-match filter on the `ANO` column; empty = all years.

## `importeMinimo` (type: `integer`):

Filtra por el importe de adjudicación sin IVA (o, si no existe, el presupuesto de licitación sin IVA). ⚠️ CKAN `datastore_search` solo admite igualdad exacta en `filters` (no rangos): este filtro se aplica EN CLIENTE, tras traer cada página del servidor. / CKAN's datastore filters only support exact match, not ranges — applied CLIENT-SIDE after each server page.

## `importeMaximo` (type: `integer`):

Igual que `importeMinimo` pero como cota superior (también en cliente). / Same as `importeMinimo`, upper bound (also client-side).

## `incluirContactosNominales` (type: `boolean`):

DESACTIVADO POR DEFECTO. El campo `NIF ADJUDICATARIO` del registro incluye NIFs sin enmascarar de personas físicas (autónomos) en una parte de los contratos menores y mayores — verificado con curl (muestra real: NIFs con máscara `***NNNN**` igual que en BDNS). Con esta opción desactivada, si el adjudicatario no es inequívocamente una persona jurídica, `adjudicatario.nif` y `.razonSocial` se anulan y solo queda `.tipoPersona`. Activarla incluye datos personales: su tratamiento y redifusión quedan bajo tu responsabilidad (RGPD / LOPDGDD). / OFF by default — sole-trader awardees' name/tax-ID are nulled unless enabled.

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

Número máximo de contratos a guardar en el dataset. El actor para limpiamente al alcanzarlo. / Hard cap on dataset items.

## Actor input object example

```json
{
  "tipoRegistro": "mayores",
  "keywords": [
    "limpieza"
  ],
  "tipoContrato": "",
  "incluirContactosNominales": false,
  "maxItems": 50
}
```

# Actor output Schema

## `results` (type: `string`):

Contratos públicos de la Comunidad Autónoma de Aragón normalizados. JSON, CSV o Excel.

# 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 = {
    "keywords": [
        "limpieza"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("xamto1987/aragon-tenders").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 = {
    "keywords": ["limpieza"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("xamto1987/aragon-tenders").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 '{
  "keywords": [
    "limpieza"
  ],
  "maxItems": 50
}' |
apify call xamto1987/aragon-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xamto1987/aragon-tenders"
        }
    }
}

```

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/fZcEMAUEz7IdrEFpW/builds/7NQm2PLyt1SHEExce/openapi.json
