# Todocoleccion Scraper — Antiques & Auctions (`reventadata/todocoleccion-scraper`) Actor

Browses any todocoleccion.net category and returns every lot with its price, auction end time, bid count and offer flag as separate columns. Fixed-price and auction lots are modelled apart, so you can filter to one or the other.

- **URL**: https://apify.com/reventadata/todocoleccion-scraper.md
- **Developed by:** [reventadata](https://apify.com/reventadata) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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

> **Unofficial.** This Actor is not affiliated with, authorised by, endorsed by, or in any
> way officially connected to Todocoleccion. "Todocoleccion" is a trademark of its
> respective owner and is used here only to describe what this tool reads. It reads the
> same public pages a browser does.

Todocoleccion Scraper browses any category on
[todocoleccion.net](https://www.todocoleccion.net) — Spain's largest marketplace for
collectibles, antiques, coins, stamps, books, militaria and watches — and returns every
lot with its price, **auction end time, bid count and offer flag as separate columns**.

### What data can you extract from Todocolección?

Most lots on todocoleccion.net are running auctions, not fixed-price listings, and the
site renders both with the same price element. This Actor tells them apart: `isAuction`,
`auctionEndsAt` and `bidCount` are first-class fields, `acceptsOffers` marks a fixed-price
lot whose seller invites an offer, and you can restrict a run to one kind or the other.
Everything is read from the site's own server-rendered pages — no browser, no login.

### Why scrape Todocolección?

- **Auctions modelled properly.** An end time you can sort by and a live bid count, not a
  "7d 0h" string you have to re-parse. Watch a category for lots closing today.
- **Fixed price and auction, separated.** `saleType` uses the site's own *venta directa*
  listing when you want fixed-price stock only, so the filtering happens server-side.
- **Category browsing, by design.** todocoleccion.net's `robots.txt` reserves its
  free-text search endpoint and explicitly re-allows paged category browsing, so that is
  the only surface this Actor requests. Point it at a category slug and it walks the
  catalogue the way the site publishes it.
- **Optional deep read.** Turn on `fetchItemDetails` and each lot page adds its
  description, condition, cheapest shipping, full category path and seller type.
- **Private sellers stay private.** Seller *type* is returned for every row; seller
  *identity* only for professional shops. See Privacy below.

### How to scrape Todocolección

1. Open a category on the site and copy its slug from the address bar — `/s/relojes`
   gives `relojes`. Put one or more slugs in `categories`.
2. Optionally narrow with `saleType`, a price bound, or `sortBy`.
3. Optionally turn on `fetchItemDetails` for condition, description and seller type.
4. Run it. Results land in the dataset.

#### Input

| Field | Type | Meaning |
|---|---|---|
| `categories` | array | One or more category slugs, for example `relojes`. Required. |
| `saleType` | string | `any` | `fixed` (venta directa) | `auction`. |
| `minPrice` / `maxPrice` | integer | Optional, in whole euros. Omitted entirely when empty — never defaulted. See the note on price bounds below. |
| `sortBy` | string | `default` | `priceAsc` | `priceDesc`. |
| `fetchItemDetails` | boolean | Open each lot page for description, condition, shipping, category path and seller type. Off by default. |
| `sellerType` | string | `any` | `private` | `professional`. Requires `fetchItemDetails`. |
| `maxItems` | integer | Hard cap on rows pushed. Default 300. |
| `maxPages` | integer | Pages per category, clamped to the site's ceiling of 1000. |

```json
{
    "categories": ["relojes"],
    "saleType": "auction",
    "minPrice": 50,
    "sortBy": "priceAsc",
    "maxItems": 300
}
```

#### Output

```json
{
    "id": "521038857",
    "title": "Antiguo reloj de sobre mesa despertador swiza mignon",
    "url": "https://www.todocoleccion.net/despertadores-antiguos/antiguo-reloj-sobre-mesa-despertador-swiza-mignon~x521038857",
    "category": "relojes",
    "subcategory": "Relojes despertadores antiguos",
    "subcategoryUrl": "https://www.todocoleccion.net/s/relojes-despertadores",
    "price": 20,
    "currency": "EUR",
    "isAuction": true,
    "auctionEndsAt": "2026-09-01T23:00:00+02:00",
    "bidCount": 0,
    "acceptsOffers": false,
    "imageUrl": "https://cloud10.todocoleccion.online/despertadores-antiguos/tc/2024/12/22/12/521038857_tcimg_E227C3F9.jpg?size=292x292&crop=true"
}
```

With `fetchItemDetails` on, each row also carries `description`, `condition`,
`shippingFrom`, `categoryPath` and `sellerType`. Professional-seller rows carry seven
more — `sellerName`, `sellerId`, `sellerProfileUrl`, `sellerLocation`, `sellerSince`,
`sellerRating` and `sellerRatingCount`.

### Notes and limits

- **30,000 lots per query, and that is the site's limit, not this Actor's.**
  todocoleccion.net serves at most 1000 pages of 30 lots for any one query. Page 999
  returns distinct lots; page 1000 and beyond silently re-serve an identical set rather
  than returning an error. One category can hold far more than that — `relojes` alone
  lists over 109,000 lots — so full coverage means splitting a run by subcategory, price
  band or sort order and treating each as its own query. This Actor stops at the ceiling
  and says so in the log.
- **Only one price bound is sent to the site per request.** todocoleccion.net answers
  HTTP 403 to any request carrying a minimum and a maximum together — a quirk of the
  site, reproduced on both a narrow and a wide band. When you set both, the minimum goes
  to the site and the maximum is applied to the results afterwards. The rows you get are
  the same; only the request shape differs.
- **`condition` is the site's own Spanish sentence, verbatim** — for example
  `Normal (con señales de uso normal)`. It is not mapped to a grade, because the site's
  full condition vocabulary has not been measured and a half-known enum would quietly
  mislabel lots.
- **`price` means two different things**, and `isAuction` is how you tell which: the
  asking price on a fixed-price lot, the current or opening bid on an auction lot. The
  site renders both in the same element.
- **Auctions dominate.** 23 of 30 lots on a sampled unfiltered page were auctions, so
  `auctionEndsAt` and `bidCount` are populated on most rows and null on the rest.
- **Opening every lot page costs about 30 times more traffic** than the results grid,
  which carries 30 lots per request. `fetchItemDetails` is off by default for that reason.
- **A run that returns zero rows fails rather than succeeding empty**, so a silent
  misconfiguration cannot look like "no stock today". A genuinely empty query is
  recognised from the site's own `0 lotes` count, not from an absence of rows.
- **A bad category slug is an error, not silent nationwide results.** The site answers a
  wrong slug with HTTP 404, which is reported rather than followed.

### Privacy

todocoleccion.net states, on every lot page and in its own words, whether the seller is
registered as a business or as a private individual. GDPR protects natural persons, not
legal entities, so this Actor treats the two differently:

- **Private sellers:** `sellerType` is returned as `private`. `sellerName`, `sellerId`,
  `sellerProfileUrl`, `sellerLocation`, `sellerSince`, `sellerRating` and
  `sellerRatingCount` are **absent from the row entirely** — not empty, absent.
- **Professional (business) sellers:** those seven fields are returned, because a shop is
  a business, not a natural person.

No real name, phone number, email address or street address is collected for anyone. With
`fetchItemDetails` off, no seller information is collected at all: the results grid
publishes none.

### How much does it cost to scrape Todocolección?

Pricing is pay-per-event: **$0.001 per result** written to the dataset (**$1.00 per 1,000
results**), plus **$0.00005** charged once when the run starts. There is no subscription —
you pay only for what you get.

### FAQ

**Is a proxy required to scrape Todocolección?** Yes. This Actor routes through Apify's
residential proxy — measured 25 of 25 pages through it against 0 of 25 with no proxy at
all. There is no `proxyConfiguration` input to set: the residential route is wired in
internally so a run can't be accidentally misconfigured onto the transport that doesn't
work.

**Is seller identity included in the output?** Only for professional sellers, and only
with `fetchItemDetails` on. Private-seller rows never carry `sellerName`, `sellerId`,
`sellerProfileUrl`, `sellerLocation`, `sellerSince`, `sellerRating` or `sellerRatingCount` —
those fields are absent from the row, not empty.

**Does this Actor search by free text?** No — it browses categories. todocoleccion.net's
own `robots.txt` reserves its free-text search endpoint while explicitly re-allowing paged
category browsing, so category browsing is the only surface this Actor requests.

### More second-hand marketplace scrapers

| Actor | What it scrapes |
|---|---|
| [Wallapop Scraper](https://apify.com/reventadata/wallapop-scraper) | Wallapop, Spain — any keyword, phone mode with battery-health parsing |
| [Wallapop + Vinted + Milanuncios Scraper — Spain](https://apify.com/reventadata/wallapop-vinted-milanuncios-scraper) | Wallapop, Vinted and Milanuncios in Spain — one keyword, one merged table |
| [Cash Converters Spain Scraper](https://apify.com/reventadata/cashconverters-scraper) | Cash Converters Spain — graded second-hand stock with price when new |
| [Milanuncios Scraper](https://apify.com/reventadata/milanuncios-scraper) | Milanuncios — 17 categories, condition, storage and battery-health filters |
| [Gumtree UK Scraper](https://apify.com/reventadata/gumtree-scraper) | Gumtree UK — any category, vehicle and phone details parsed from the ad's own text |
| [OLX Romania Scraper](https://apify.com/reventadata/olx-ro-scraper) | OLX Romania (olx.ro) — any keyword, no proxy required |
| [OLX Brazil Scraper](https://apify.com/reventadata/olx-scraper) | OLX Brazil (olx.com.br) — any category, structured attributes from the site's own detail chips |
| [Vinted Spain Scraper](https://apify.com/reventadata/vinted-scraper) | Vinted Spain (vinted.es) — any keyword or category, no proxy required |
| [Back Market Spain Scraper](https://apify.com/reventadata/backmarket-scraper) | Back Market Spain — refurbished phones, laptops and tablets, priced against new |
| [eBay Spain Scraper](https://apify.com/reventadata/ebay-scraper) | eBay Spain (ebay.es) — active listings with seller type |

# Actor input Schema

## `categories` (type: `array`):

One or more todocoleccion.net category slugs, taken from the address bar of a category page — /s/relojes gives the slug 'relojes'. Each is browsed in turn. Free-text search is deliberately not offered: the site's robots.txt reserves its search endpoint, and explicitly re-allows paged category browsing instead.

## `saleType` (type: `string`):

Fixed-price only uses the site's own /venta-directa listing, which removes every auction lot server-side. Auctions only is applied after fetching, because the site publishes no auctions-only listing of its own.

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

Optional, in whole euros. Omitted from the request entirely when empty — never defaulted to 0. Sent as the site's own preciodesde filter.

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

Optional, in whole euros. Sent as the site's own preciohasta filter when it is the only bound given. If you set a minimum as well, the maximum is applied after fetching instead — todocoleccion.net answers HTTP 403 to any request carrying both price bounds at once.

## `sortBy` (type: `string`):

Order only; changes nothing about which lots exist. Cheapest first fills with 0,01 EUR lots and most expensive first with five-figure outliers, so pair either with a price bound for a usable band. Only the two sort values confirmed to change the results are offered.

## `fetchItemDetails` (type: `boolean`):

Off by default. When on, each lot's own page is fetched to add its description, condition, cheapest shipping, full category path and seller type. It costs roughly 30 times more proxy traffic than the results grid alone, because the grid carries 30 lots per request and a lot page carries one.

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

Keep only private sellers or only professional (business) sellers, using the site's own registration sentence on the lot page. Requires 'Open each lot page' — the results grid publishes no seller information at all.

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

Hard cap on rows pushed across all categories.

## `maxPages` (type: `integer`):

todocoleccion.net serves at most 1000 pages of 30 lots (30,000 lots) for any one query. Past page 999 it silently re-serves the same lots rather than returning an error. Clamped to that ceiling.

## Actor input object example

```json
{
  "categories": [
    "relojes"
  ],
  "saleType": "any",
  "sortBy": "default",
  "fetchItemDetails": false,
  "sellerType": "any",
  "maxItems": 300,
  "maxPages": 1000
}
```

# Actor output Schema

## `matches` (type: `string`):

Matching lots: price, auction end time, bid count, offer flag, subcategory and a link to the lot.

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

// Run the Actor and wait for it to finish
const run = await client.actor("reventadata/todocoleccion-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 = { "categories": ["relojes"] }

# Run the Actor and wait for it to finish
run = client.actor("reventadata/todocoleccion-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 '{
  "categories": [
    "relojes"
  ]
}' |
apify call reventadata/todocoleccion-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reventadata/todocoleccion-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/RHCwqU27foHSK82hD/builds/IIrD71S0ZBTOKAXIj/openapi.json
