# CEPiK Vehicle Registrations API – Poland Official Stats (`enterprising_hamster/polish-vehicle-registrations-cepik`) Actor

CEPiK vehicle registration statistics for Poland from the official open data API: monthly counts by make, model, fuel, powertrain (EV, hybrid), origin, year and region. Aggregates only, no VINs or owners. Export CSV, JSON or Excel.

- **URL**: https://apify.com/enterprising_hamster/polish-vehicle-registrations-cepik.md
- **Developed by:** [Kamil Kaczmarek](https://apify.com/enterprising_hamster) (community)
- **Categories:** Travel, Automation
- **Stats:** 1 total users, 1 monthly users, 44.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 statistics rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## Poland Vehicle Registrations API – Official CEPiK Statistics

**Poland vehicle registrations API**: monthly **vehicle registration statistics for Poland** from the official **CEPiK** register (**Centralna Ewidencja Pojazdów i Kierowców**), read live from the public open-data API `api.cepik.gov.pl`. Count new car registrations, used-car imports, EV and hybrid registrations by **make, model, fuel, powertrain, origin, production year, voivodeship and county**, ready for dashboards, market reports and AI agents; export CSV, JSON or Excel. The Actor outputs **aggregate counts only**: no VINs, no plate numbers, no owners. Polski opis: **rejestracje pojazdów** z CEPiK (api.cepik.gov.pl) — miesięczne agregaty po marce, modelu, paliwie, napędzie (EV, hybryda), pochodzeniu i województwie; bez VIN, tablic i właścicieli.

### What data can you get

One row per **month × area × group**, for example "September 2026, all of Poland, TESLA MODEL Y: 529 new electric passenger cars".

- **Months:** any calendar month from 1990 on, up to 60 per run. The running month is counted up to today and flagged `partialPeriod`.
- **Areas:** Poland as a whole, any set of voivodeships summed, or each voivodeship separately.
- **Group by** any combination of: `brand` (make), `model`, `fuelType`, `alternativeFuel`, `powertrain` (ELECTRIC, HYBRID, PETROL, DIESEL, GAS, HYDROGEN, OTHER), `vehicleType`, `origin` (new/used, bought in Poland/imported), `condition` (NEW/USED/OTHER), `productionYear`, `county` (powiat).
- **Filters** applied by CEPiK before counting: vehicle type (passenger car, truck, motorcycle, bus, tractor, trailer and more), primary fuel, origin, exact make and model.
- **Date basis:** first registration in Poland (new cars plus imported used cars, the usual "registrations" market figure) or last registration (also counts re-registrations after a change of owner).
- Every row carries its rank, its share of the month's total and the total itself.

### How to use

1. Open the Actor and press **Start**. With no changes you get the most registered **electric passenger car models in Mazowieckie (Warsaw region) in the last complete month** (about a minute). Clear **Voivodeships** for all of Poland.
2. To see the whole car market, set **Primary fuel** to *Any fuel* and keep **Group by** on make and model.
3. For regional reports set **Area level** to *Each voivodeship separately*. For one total per month, empty **Group by**.
4. Schedule it monthly with **Only new or changed rows** switched on to receive just the new month.

### Input

Top EV passenger-car models in Mazowieckie (Warsaw region), last complete month (default-style market cut):

```json
{ "voivodeships": ["14"], "fuelType": "ELECTRIC", "groupBy": ["brand", "model"], "maxItems": 100 }
```

New passenger cars by powertrain per voivodeship (EV / hybrid share over three months):

```json
{
  "monthFrom": "2026-07",
  "monthTo": "2026-09",
  "areaLevel": "VOIVODESHIP",
  "voivodeships": [],
  "groupBy": ["powertrain"],
  "fuelType": "ANY",
  "vehicleType": "PASSENGER_CAR",
  "origin": "NEW_BOUGHT_IN_POLAND",
  "maxItems": 500
}
```

| Field | Default | What it does |
|---|---|---|
| `monthFrom`, `monthTo` | last complete month | Month range, `YYYY-MM`. Only `monthFrom` = up to the current month. |
| `areaLevel` | `POLAND` | `POLAND` (one total) or `VOIVODESHIP` (one block per region). |
| `voivodeships` | `["14"]` (Mazowieckie) | TERYT codes. An empty list `[]` = all of Poland (17 codes, several minutes when CEPiK is busy). `XX` = records without a voivodeship. |
| `groupBy` | `["brand","model"]` | Columns to count by. `[]` = totals only (fastest). |
| `vehicleType` | `PASSENGER_CAR` | `ANY` or one CEPiK vehicle type. |
| `fuelType` | `ELECTRIC` | `ANY` or one primary fuel. Hybrids have petrol or diesel as primary fuel: group by `powertrain` to see them. |
| `origin` | `ANY` | e.g. `NEW_BOUGHT_IN_POLAND`, `USED_IMPORTED`. |
| `brand`, `model` | none | Exact make or model as registered (case-insensitive). |
| `dateBasis` | `FIRST_REGISTRATION_IN_POLAND` | or `LAST_REGISTRATION`. |
| `onlyCurrentlyRegistered` | `true` | CEPiK's default: vehicles deregistered since are not counted. |
| `topN` | `0` | Keep the N largest groups per month and area (0 = all). |
| `minRegistrations` | `1` | Skip smaller groups. |
| `maxItems` | `100` | Hard cap of rows, and so of cost. |
| `onlyNew`, `stateKey` | `false`, `default` | Skip rows already delivered with the same count. |
| `cacheTtlHours` | `24` | Reuse breakdowns of more than 1,000 records that your earlier runs read within this many hours; `0` = always ask CEPiK. |
| `maxRequestsPerSecond` | `1` | Politeness limit; requests always go one at a time. |

Example inputs are in [`examples/`](examples): hybrid and EV share of new cars per voivodeship, monthly totals of all vehicles for 2025, top used-import models in Mazowieckie.

### Output

Real row from a run on 2026-10-21 for all of Poland (`"voivodeships": []`, other fields default; shortened):

```json
{
  "period": "2026-09",
  "periodStart": "2026-09-01",
  "periodEnd": "2026-09-30",
  "partialPeriod": false,
  "dateBasis": "FIRST_REGISTRATION_IN_POLAND",
  "areaLevel": "POLAND",
  "areaCode": "PL",
  "area": "POLSKA",
  "brand": "TESLA",
  "model": "MODEL Y",
  "fuelType": null,
  "powertrain": null,
  "registrations": 529,
  "rank": 1,
  "sharePct": 11.55,
  "areaPeriodTotal": 4579,
  "filters": {"vehicleType": "SAMOCHÓD OSOBOWY", "fuelType": "ENERGIA ELEKTRYCZNA", "origin": null, "brand": null, "model": null},
  "onlyCurrentlyRegistered": true,
  "source": "CEPiK, Centralna Ewidencja Pojazdów i Kierowców (Central Register of Vehicles and Drivers), Ministerstwo Cyfryzacji, via api.cepik.gov.pl",
  "sourceUrl": "https://dane.gov.pl/pl/dataset/1558",
  "license": "CC BY 4.0 (dane.gov.pl dataset 1558); commercial reuse allowed with source attribution",
  "retrievedAt": "2026-10-21T19:35:14Z"
}
```

Columns you did not group by are `null`. Values (makes, models, fuels) are the Polish strings stored in the register. Model names are as registered, with a repeated make removed (`TOYOTA C-HR` counts as `C-HR`); other spelling variants are not merged. The key-value store record `SUMMARY` lists pages read, cache hits, CEPiK inconsistencies that were re-read and any region that failed.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `statistics-row` | $0.003 | One delivered row (one month × area × group, or one total). |

You pay only for rows. Requests, retries and cache hits are free. Examples: the default run (top EV models, up to 100 rows) costs at most $0.30; one monthly total for each of the 17 voivodeship codes costs 17 × $0.003 = $0.051; `maxItems` caps every run.

### Use cases

- **Automotive market analysis:** monthly new-car and used-import registrations by make and model, like the paid registration reports sold to the industry.
- **EV and hybrid adoption tracking:** electric and hybrid share per voivodeship and month for policy, charging-network planning and journalism.
- **Dealers, leasing and insurers:** regional demand per model and production year.
- **Data pipelines and AI agents:** clean JSON with stable `rowId`s for BI tools, spreadsheets, LLM agents and RAG.
- **Research:** fleet renewal, import of used cars, fuel mix over time.

### FAQ

**Is there an API for Polish vehicle registrations (CEPiK)?** CEPiK publishes a public open-data API at `api.cepik.gov.pl` (dataset on dane.gov.pl under CC BY 4.0). This Actor turns those live queries into one filterable table of **monthly registration aggregates** callable from the Apify API, with CSV/JSON/Excel export.

**How do I export Polish vehicle registration stats to CSV or Excel?** Set the month range, filters and Max items, run the Actor, then download the dataset as CSV or Excel from the run page or via the Apify API.

**Do you include VINs, plate numbers or owners?** No. The Actor outputs **aggregate counts only** (month × area × group). Record IDs, VINs, plates and owners are never returned.

**What is the difference vs Otomoto / Autoplac scrapers?** Listing scrapers are classified ads (asking prices, contacts). This Actor reads the **official CEPiK register**: how many vehicles were actually registered, by make, model, fuel, powertrain, origin and region.

**Where does the data come from and may I use it commercially?** From the public CEPiK API run by the Ministry of Digital Affairs (Ministerstwo Cyfryzacji). gov.pl states: "Dane z CEPiK można wykorzystywać do celów komercyjnych i niekomercyjnych. W obu przypadkach musisz poinformować o źródle wytworzenia i pozyskania informacji." (CEPiK data may be used for commercial and non-commercial purposes; in both cases you must state the source.) The dataset is published on dane.gov.pl under CC BY 4.0. Every row carries `source`, `sourceUrl` and `license`, so keep them, or name the source, when you publish results.

**Is there personal data?** No. The API serves technical vehicle records without VINs, plates or owners. This Actor reads only the columns you group by and outputs only counts. Record IDs are never output.

**Why can my numbers differ from published registration statistics?** By default CEPiK counts only vehicles that are still registered today (`onlyCurrentlyRegistered`), so older months lose vehicles that were deregistered since. First registration in Poland includes imported used vehicles. Make and model spellings are as entered at registration offices.

**How fresh is it?** Counts are read live at run time, unless your own cache from the last `cacheTtlHours` is reused (then `retrievedAt` shows when they were read). On 2026-10-21 the API already held registrations from that month.

**Is CEPiK reliable?** Mostly, with quirks this Actor handles. During testing about 1 in 20 answers carried a wrong total, some valid requests got a 404 or 429, and some bodies were cut off. Every total is accepted only after two reads agree, every page must match it, and failed reads are retried with backoff. If a region still cannot be read, the run ends as failed, keeps the rows already saved and names the region. A Poland total is never published with a region missing.

**How fast is it?** The API serves 500 records per request and has no aggregate endpoint, so breakdowns read every matching record. Totals-only runs need two small requests per month and region. The default run (one voivodeship) takes about a minute; all of Poland took about a minute (38 requests) on a quiet evening and can take several minutes when CEPiK throttles. A make × model breakdown of all passenger cars in Poland for one month reads every record of that month and takes tens of minutes at the polite default rate.

**Rate limits?** Requests go one at a time, at most 1 per second by default (max 3), with a clear User-Agent. CEPiK answers parallel clients with "maximum number of parallel connections", so there is no parallel mode. When it throttles ("too many calls, wait 60s"), the Actor waits as told before retrying.

### Integrations

Run it from the Apify API, the Apify CLI, Make, Zapier, n8n or any HTTP client; schedule monthly runs; send webhooks on finish; or call it from AI agents through the Apify MCP server. Results download as JSON, CSV, Excel or via the dataset API.

### Development

```bash
python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q          # offline tests, no network
apify run --input-file examples/smoke-ev-poland-last-month.json   # live run, no Apify login needed
examples/run-local-ppe.sh              # same, with simulated pay-per-event prices from examples/pricing_info.local.json
```

Behind an egress proxy set `LOCAL_HTTP_PROXY=http://host:port`. The CEPiK server uses a 1024-bit DH key, so the Actor lowers OpenSSL's security level for this host only; certificates are still verified.

### Disclaimer

Unofficial tool, not affiliated with or endorsed by the Ministry of Digital Affairs or CEPiK. Counts are computed from the API at run time and can differ from official publications. Source: CEPiK, Ministerstwo Cyfryzacji, api.cepik.gov.pl, CC BY 4.0.

### 🇵🇱 Po polsku

**Statystyki rejestracji pojazdów w Polsce z CEPiK.** Aktor liczy pojazdy z otwartego API CEPiK (api.cepik.gov.pl) i zwraca wyłącznie agregaty: liczbę rejestracji w miesiącu dla Polski, wybranych województw albo każdego województwa osobno, z podziałem na markę, model, paliwo, napęd (elektryczny, hybryda), pochodzenie (nowy/używany, kraj/import), rok produkcji i powiat. Bez VIN, numerów rejestracyjnych i danych właścicieli.

- **Wejście:** zakres miesięcy (`monthFrom`, `monthTo`, domyślnie ostatni pełny miesiąc), poziom obszaru, województwa (domyślnie mazowieckie; pusta lista = cała Polska), kolumny grupowania, filtry (rodzaj pojazdu, paliwo, pochodzenie, marka, model), rodzaj daty (pierwsza rejestracja w Polsce albo ostatnia rejestracja), `topN`, `maxItems`, tryb „tylko nowe”.
- **Wyjście:** jeden wiersz na miesiąc × obszar × grupę z liczbą rejestracji, pozycją, udziałem procentowym i sumą, plus źródło i licencja.
- **Cena:** `statistics-row` $0.003 za wiersz. Domyślny przebieg (do 100 wierszy) kosztuje najwyżej $0.30.
- **Źródło i licencja:** CEPiK, Ministerstwo Cyfryzacji, dane.gov.pl (CC BY 4.0). Przy publikacji wyników podaj źródło.

# Changelog

This Actor's version history is a separate document: https://apify.com/enterprising_hamster/polish-vehicle-registrations-cepik/changelog.md

# Actor input Schema

## `monthFrom` (type: `string`):

First month, YYYY-MM (e.g. 2026-01). Leave both months empty for the last complete month. With only From, the range runs to the current month (marked partialPeriod).

## `monthTo` (type: `string`):

Last month, YYYY-MM. Months are reported newest first. At most 60 months per run.

## `areaLevel` (type: `string`):

Report one total for Poland (or for the selected voivodeships together) or one block of rows per voivodeship.

## `voivodeships` (type: `array`):

Default: 14 MAZOWIECKIE. Clear the field (empty list) for all of Poland (all 16 voivodeships plus records with no voivodeship, code XX); all of Poland reads 17 voivodeships and takes several minutes when CEPiK is busy.

## `groupBy` (type: `array`):

Columns to count by. Empty = one total per month and area (fastest: counts come straight from the API without reading records).

## `vehicleType` (type: `string`):

Count only this vehicle type (exact CEPiK value).

## `fuelType` (type: `string`):

Count only this primary fuel. Hybrids are registered with petrol or diesel as primary fuel; use groupBy powertrain to see them.

## `origin` (type: `string`):

Count only vehicles of this origin, e.g. new cars bought in Poland or used imports.

## `brand` (type: `string`):

Optional exact make as registered, e.g. TOYOTA (case does not matter).

## `model` (type: `string`):

Optional exact model as registered, e.g. MODEL Y.

## `dateBasis` (type: `string`):

Which registration date puts a vehicle in a month.

## `onlyCurrentlyRegistered` (type: `boolean`):

CEPiK's default: count only vehicles that are registered today. Turn off to include vehicles deregistered since.

## `topN` (type: `integer`):

Keep only the N largest groups per month and area. 0 = all groups.

## `minRegistrations` (type: `integer`):

Skip groups smaller than this.

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

Hard cap of dataset rows (each row is one charged event).

## `onlyNew` (type: `boolean`):

Skip rows already delivered by an earlier run with the same state key and the same count. Useful for schedules.

## `stateKey` (type: `string`):

Name of the remembered set of delivered rows (letters, digits, - and \_).

## `cacheTtlHours` (type: `integer`):

Reuse breakdowns that needed more than 1,000 records and were read by an earlier run of yours within this many hours. 0 = always ask CEPiK.

## `maxRequestsPerSecond` (type: `number`):

Politeness limit towards api.cepik.gov.pl. Requests are always sent one at a time.

## Actor input object example

```json
{
  "areaLevel": "POLAND",
  "voivodeships": [
    "14"
  ],
  "groupBy": [
    "brand",
    "model"
  ],
  "vehicleType": "PASSENGER_CAR",
  "fuelType": "ELECTRIC",
  "origin": "ANY",
  "dateBasis": "FIRST_REGISTRATION_IN_POLAND",
  "onlyCurrentlyRegistered": true,
  "topN": 0,
  "minRegistrations": 1,
  "maxItems": 100,
  "onlyNew": false,
  "cacheTtlHours": 24,
  "maxRequestsPerSecond": 1
}
```

# Actor output Schema

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

One row per month, area and group.

## `summary` (type: `string`):

Pages read, cache hits, CEPiK anomalies handled and any failed voivodeships.

# 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 = {
    "voivodeships": [
        "14"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("enterprising_hamster/polish-vehicle-registrations-cepik").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 = { "voivodeships": ["14"] }

# Run the Actor and wait for it to finish
run = client.actor("enterprising_hamster/polish-vehicle-registrations-cepik").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 '{
  "voivodeships": [
    "14"
  ]
}' |
apify call enterprising_hamster/polish-vehicle-registrations-cepik --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,enterprising_hamster/polish-vehicle-registrations-cepik"
        }
    }
}
```

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/i090NPir4NEO2jxnw/builds/1IO5UqIFZoXcMk8aU/openapi.json
