# Coches.net Scraper & Used Car Price Monitor (Spain) (`neverempty/coches-net-listings-monitor`) Actor

For car dealers, resellers and price trackers: coches.net used-car listings by make, model and province with price in EUR, year, mileage, fuel, power, province, dealer name and photos. Watch mode returns only cars listed since your last check and price drops.

- **URL**: https://apify.com/neverempty/coches-net-listings-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 listing returneds

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

## Coches.net Scraper & Used Car Price Monitor (Spain)

Get used-car listings from **coches.net**, one of the biggest used-car sites in Spain, by make, model and province. One row per car: price in EUR, year, kilometres, fuel, power, environmental label, province and city, dealer or private seller, dealer name and rating, warranty, photos and link. **Watch mode** turns a search into a feed: run it on a schedule and each run returns only the cars listed since your watch started that you have not received yet, plus cars whose price went down.

No login, no cookies, no API key. It reads the public used-car list pages (`/segunda-mano/`) only.

### What you can do with it

- **Dealer stock and sourcing**: watch `toyota/corolla` in `madrid` every hour and get only the new listings, with price, year and kilometres.
- **Price tracking**: watch mode returns a `price-drop` row with the previous price and the difference when a seller lowers the price. Rows also carry the site's own price-drop note (`sitePriceDrop`).
- **Market research**: how many cars the site lists for a make, model and province (`listingsInSearch`), prices by year and mileage, dealer versus private share.
- **Lead lists of dealers**: dealer name, rating and number of reviews for every dealer car. Private sellers' names and phone numbers are never returned.

### Input

| Field | What it does |
|---|---|
| `makes` | A make or make/model as written in coches.net addresses, one per line: `toyota`, `toyota/corolla`, `volkswagen/golf`, `land_rover/range_rover_evoque`. |
| `provinces` | Optional provinces or regions as written in coches.net addresses: `madrid`, `barcelona`, `valencia`, `sta_c_tenerife`, `catalunya`. Each make line is searched in each province. Empty = all of Spain. |
| `searchUrls` | Or paste a coches.net used-car list address, such as `https://www.coches.net/toyota/corolla/segunda-mano/madrid/` or `https://www.coches.net/toyota/segunda-mano/particulares/` (private sellers). Addresses with a `?` part are refused. |
| `maxResultsPerSearch` | Cars per search, 1 to 175 (default 30). |
| `minPrice` / `maxPrice` | Price range in EUR. |
| `minYear` / `maxYear` | Registration year range. |
| `maxKm` | Highest mileage in km. |
| `sellerType` | `any` (default), `dealer` or `private`. |
| `onlyNew` | Watch mode (see below). |
| `includePriceDrops` | In watch mode, also return price drops (default on). |
| `watchPages` | In watch mode, how many pages (about 35 cars each) to read per check, 1 to 5 (default 5). |
| `watchName` | Keeps separate memories for separate schedules of the same search. |
| `resetMonitoringState` | Start a watch over. |

The price, year, mileage and seller filters are applied to the pages read: coches.net's robots.txt does not allow its own filter parameters, so this Actor never sends them.

Example: `{ "makes": ["toyota/corolla"], "maxResultsPerSearch": 30 }`

Watch example: `{ "makes": ["toyota/corolla"], "provinces": ["barcelona"], "onlyNew": true }` on a schedule.

### Output

One row per car (`status: "ok"`):

| Field | Meaning |
|---|---|
| `listingId` | The site's listing number. |
| `title` | The listing title (make, model and version as the seller wrote it). Phone numbers and email addresses in it are replaced with `[phone removed]` / `[email removed]`. |
| `make`, `model`, `year`, `km` | As the site lists them. |
| `price`, `currency`, `includesTaxes` | Price in EUR (`null` if the site shows none) and whether it includes VAT. |
| `financedPrice` | The lower price the site shows when the car is bought with the dealer's financing, when there is one. |
| `sitePriceDrop` | The site's own note when the seller lowered the price: `originalPrice`, `percentage`, `daysSinceUpdate`. |
| `previousPrice`, `priceChange` | Watch mode, `price-drop` rows only (prices seen by this Actor). |
| `fuelType`, `hp`, `environmentalLabel`, `offerType` | Fuel as the site writes it (`Gasolina`, `Diésel`, `Híbrido`, `Híbrido enchufable`, `Eléctrico`), power, the DGT label (`0`, `ECO`, `C`, `B`), and `Ocasión` or `Km0`. |
| `province`, `region`, `city` | Where the car is. |
| `sellerType` | `dealer` or `private`. |
| `dealerName`, `dealerRating`, `dealerReviews` | Dealer cars only. `null` for private sellers. |
| `hasWarranty`, `warrantyMonths`, `isCertified`, `hasReservation` | As shown on the site. |
| `isPromoted` | `true` for paid top listings (shown at the top of each page). |
| `createdAt`, `publishedAt` | When the listing was created and when it was last published, as the site gives them. |
| `imageUrl`, `imageUrls`, `url` | Photos and the link to the car. |
| `positionInSearch`, `listingsInSearch` | Position in the list read, and the total the site shows for the search. |
| `changeType` | Watch mode: `first-check`, `new` or `price-drop`. |
| `searchMake`, `searchModel`, `searchProvince`, `searchUrl`, `watchName`, `checkedAt` | Which search the row came from. |

The gearbox (manual or automatic) is not on the list pages, so it is not returned.

In the pages read while building this Actor (312 cars, 9 pages, October 2026): 100% had a price, year, kilometres, fuel and photo; 97% had the power; 86% had the environmental label; 85% were dealer cars (one of the 9 pages was a private-sellers-only list).

### Watch mode, and what "new" means here

The first run returns the cars it reads and remembers them (`first-check`). Every later run returns:

- `new`: a car you have not received that was **listed after the watch started**. The site numbers listings in the order they are created, so a listing whose number is higher than the highest number seen at the first check is new. An old listing that rises in the order is not called new.
- `price-drop`: a car you already received whose price went down. Price rises are remembered, not returned.

A check that finds nothing returns one free `no-new-listings` row and is charged as one small `search-checked` event. Cars that could not be returned because of your run's maximum charge are not marked as delivered, and the next run returns them.

### What one run can read (please read before you schedule)

- coches.net lists cars **by relevance, with paid top listings first, not by date**, and its robots.txt does not allow the sort parameter. A new listing can sit on any page.
- Its robots.txt allows only the **first 6 pages** of a list, and the site shows a check page after about **5 list pages** from one IP address. This Actor does not solve or bypass check pages and does not switch addresses to get around them, so **one run reads at most 5 list pages in total** (about 170 cars).
- So **watch one make/model in one province per schedule**. Most model and province lists are under 170 cars (for example, the Toyota Corolla is listed in 47 provinces and 46 of them had under 170 cars in October 2026), and then a watch sees the whole list. If a list is longer, the first check says so in a free `watch-coverage` row.
- Up to 10 searches per run are accepted, but searches after the 5-page limit come back as a free `not-read-page-limit` row. Make one schedule per search instead.

### Rows that explain instead of data (never charged)

`no-results`, `not-found` (unknown make, model or province: the site answers with a different list, which this Actor does not sell), `none-matching-filters`, `no-new-listings`, `watch-coverage`, `incomplete` (a later page could not be read), `blocked` (the site showed a check page), `not-read-page-limit`, `unreadable`, `not-allowed-by-robots-txt`, `bad-input`, `budget-reached`, `more-not-returned`. Each has a `note` that says what happened.

### Limits

- At most 5 list pages per run, about 35 cars per page.
- Pages are read one by one with a 3-second pause between them.
- The site's robots.txt is read on every run, and pages it does not allow are not requested.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `makes` (type: `array`):

Which used cars to list, one per line, written as in coches.net addresses: a make (toyota, bmw, seat) or make/model (toyota/corolla, volkswagen/golf, land_rover/range_rover_evoque). If this and the URLs below are both empty, the example toyota/corolla is searched. Each run reads at most 5 list pages in total, so schedule one run per search for watches.

## `provinces` (type: `array`):

Optional. Spanish provinces or regions as written in coches.net addresses, one per line (madrid, barcelona, valencia, sta_c_tenerife, catalunya, andalucia). Each make line is searched in each province. Empty searches all of Spain.

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

Or paste the address of a coches.net used-car list, such as https://www.coches.net/toyota/corolla/segunda-mano/madrid/ or https://www.coches.net/toyota/segunda-mano/particulares/. Addresses with a ? part are refused, because coches.net's robots.txt does not allow its filter and sort parameters.

## `maxResultsPerSearch` (type: `integer`):

How many cars to return for each search, from 1 to 175. coches.net shows about 35 per page, and this Actor reads at most 5 list pages per run (a check page appears after about 5 pages from one IP address). In watch mode, the most rows one check returns per search.

## `minPrice` (type: `integer`):

Return only cars priced at or above this many euros. Applied to the pages read. Empty means no minimum.

## `maxPrice` (type: `integer`):

Return only cars priced at or below this many euros. Applied to the pages read. Empty means no maximum.

## `minYear` (type: `integer`):

Return only cars registered in this year or later (for example 2019). Applied to the pages read. Empty means no limit.

## `maxYear` (type: `integer`):

Return only cars registered in this year or earlier. Applied to the pages read. Empty means no limit.

## `maxKm` (type: `integer`):

Return only cars with at most this many kilometres. Applied to the pages read. Empty means no limit.

## `sellerType` (type: `string`):

Return cars from any seller, only dealers, or only private sellers. Applied to the pages read. Dealer names are returned; private sellers' names and phone numbers are never returned.

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

Run the same search on a schedule. The first run returns the cars it reads and remembers them. Every later run returns only listings created since the watch started that you have not received yet, and cars whose price went down. A check that finds nothing is charged as one small search-checked event instead of rows.

## `includePriceDrops` (type: `boolean`):

In watch mode, also return cars you already received when their price went down, with the previous price and the difference. Price rises are remembered but not returned.

## `watchPages` (type: `integer`):

How many pages (about 35 cars each) a watch reads per search on each check, from 1 to 5 (5 pages per run in total). coches.net does not sort by date, so a new listing can sit on any page; watch a make/model in one province so that these pages cover the whole list (most model and province lists have under 170 cars).

## `watchName` (type: `string`):

Optional. A name for this watch (letters, digits, dot, dash, underscore). Two schedules with the same search but different names keep separate memories. Empty uses one shared default watch.

## `resetMonitoringState` (type: `boolean`):

Start this watch over: the run is treated as the first check again. Off by default.

## Actor input object example

```json
{
  "makes": [
    "toyota/corolla"
  ],
  "maxResultsPerSearch": 30,
  "sellerType": "any",
  "onlyNew": false,
  "includePriceDrops": true,
  "watchPages": 5,
  "resetMonitoringState": false
}
```

# Actor output Schema

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

One row per coches.net used-car listing: listing ID, title, make, model, year, kilometres, price in EUR (with financed price and the site's own price-drop note), fuel, power, environmental label, province, region and city, dealer or private seller, dealer name and rating, warranty, photos, link and position. Watch mode marks rows first-check, new or price-drop (with the previous price). A search with no cars, nothing new, an unknown make, a page robots.txt does not allow, a check page or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "makes": [
        "toyota/corolla"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/coches-net-listings-monitor").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 = { "makes": ["toyota/corolla"] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/coches-net-listings-monitor").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 '{
  "makes": [
    "toyota/corolla"
  ]
}' |
apify call neverempty/coches-net-listings-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/coches-net-listings-monitor"
        }
    }
}
```

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/BPSowGldoZJINcWAz/builds/Fbj8ajtitrtDHWG6a/openapi.json
