# Subito.it Classifieds Scraper - Italy Marketplace (`scrapyx/subito-classifieds-scraper`) Actor

Scrapes subito.it, Italy's largest classifieds marketplace: cars, property, electronics, jobs and 38 more categories across all 20 regions. Returns price, location, seller type, images and every category attribute, with honest reporting of subito's 9,000-item paging wall.

- **URL**: https://apify.com/scrapyx/subito-classifieds-scraper.md
- **Developed by:** [Ibnu Adzim](https://apify.com/scrapyx) (community)
- **Categories:** E-commerce, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

## Subito.it Classifieds Scraper — Italy's Largest Marketplace

Every listing on **subito.it**: cars, motorbikes, property, electronics,
furniture, jobs and 36 more categories, across all 20 Italian regions.

Price, location down to the town, seller type, images and every
category-specific attribute upstream publishes. No API key, no login.

***

### The number subito shows you is mostly out of reach

Search "auto" nationwide and subito reports **530,881 listings across 17,697
pages**. It will serve you **300** of them.

Page 300 returns rows; **page 301 is a hard HTTP 404**. That is 9,000 items —
**1.7%** of what the page's own counter advertises — and the cap is fixed, not
proportional: a region with 114 real pages hits the same wall.

A scraper that trusts `totalPages` walks into that 404 at page 301 and either
crashes or stops quietly while still reporting half a million results. This
one reports the gap on every query:

| Field | Meaning |
|---|---|
| `totalAvailable` | what subito says exists |
| `reachableItemCeiling` | 9,000 — what any single query can actually page to |
| `itemsUnreachableByPaging` | the difference, per query |
| `reachableCeilingHit` | whether this run hit the wall |

**The way past it is to partition, not to page harder.** Region and category
are path segments and both genuinely filter, so twenty regions × forty-two
categories is 840 independent 9,000-item windows rather than one.

***

### What you get

Three record types share one dataset, told apart by `recordType`:

- **`LISTING`** — title, description, price in euro, publication timestamp,
  region / province / town, listing URL, every image URL, the advertiser
  (dealer trading name, shop id, private-vs-dealer flag), and **`features`**:
  upstream's own attribute set for that category, kept verbatim. A car carries
  `/fuel`, `/gearbox`, `/mileage`, `/power`, `/year`, `/car` (make, model,
  trim); a flat carries entirely different ones. Nothing is renamed, so a
  category this actor's author never opened still comes through whole.
- **`SEARCH_SUMMARY`** — one per region × category: filters applied,
  upstream's echo of what it actually searched, the totals above, and every
  honesty flag.
- **`ERROR`** — one per input that failed, so **every input maps to at least
  one row**.

Every row carries `_input`, `_source`, `_scrapedAt`, `recordType`.

***

### Filters, and only the ones that work

Every offered filter was verified twice: the result total had to move by far
more than churn (subito's baseline is perfectly stable — three identical
requests returned 530,881 every time), **and** every returned row had to
satisfy it.

| Input | Verified |
|---|---|
| `categories` / `regions` | path segments; upstream echoes both back, checked before paging |
| `query` + `titleOnly` | a real keyword narrows 530,881 → 37,118 and 30/30 rows match; nonsense returns an **honest zero** |
| `advertiserType` | private 290,112 + dealer 240,815 ≈ the 530,881 baseline — the two halves partition the catalogue |
| `minPrice` / `maxPrice` | 30/30 rows inside the range |
| `sortOrder` | `priceasc` returns €1 listings, `pricedesc` returns €9,999,999 ones |

Parameters that subito **accepts and silently ignores** (`t`, `urg`, `ndo` —
each moves the total by under 100 out of 530,881, and *upward*) are refused
with an explanation rather than offered as no-ops.

For category-specific attributes there is **`extraFilters`**, a raw
passthrough — and because unknown parameters are ignored in silence, supplying
it makes the run fetch the same search *without* them and report both totals
in `extraFiltersChangedTotal`. Whether your filter did anything is a field,
not a guess.

***

### Known limits

- **9,000 items per query**, however large the total. Partition by region,
  category or price.
- **No seller names for private sellers.** `advertiser.name` is empty for
  everyone on the search surface; dealers are named via their shop, private
  sellers are not named at all. No phone numbers are exposed here either.
- Listing **detail pages are not fetched** — the search rows already carry the
  full description and every image, so a detail pass would multiply requests
  for almost nothing.
- Only `vendita` (for sale) listings; subito's `/acquisto/` path does not
  exist.
- **DataDome is on this domain.** It never fired during recon and rarely fires
  in normal use, but it triggers on request *rate*: the actor backs off 8 s /
  20 s / 45 s and tells you to raise `minRequestInterval` or lower
  `maxConcurrency`. A residential proxy is the next step if it persists.

# Actor input Schema

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

Which subito categories to search. Cars, motorbikes, property, electronics, jobs and more — 42 verified categories. An unknown one is refused up front, because subito answers it with a bare HTTP 404.

## `regions` (type: `array`):

Italian regions to search, or 'italia' for the whole country. Each region x category pair runs as its own query with its own summary row.

## `query` (type: `string`):

Free-text search, e.g. 'bmw serie 3'. A phrase that matches nothing returns an honest zero rather than the unfiltered list.

## `titleOnly` (type: `boolean`):

Restrict the keyword to ad titles instead of titles and descriptions.

## `advertiserType` (type: `string`):

Private sellers or dealers/businesses. Verified against upstream's own vocabulary — the two values partition the catalogue exactly (290,112 private + 240,815 dealer against a 530,881 baseline).

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

Lower bound on the listing price.

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

Upper bound on the listing price.

## `sortOrder` (type: `string`):

Result ordering. Only the values subito publishes for the category are honoured; year and mileage sorts apply to vehicle categories.

## `maxItemsPerQuery` (type: `integer`):

Stop each region x category query after this many listings. Set 0 for as many as subito will serve — but note its hard wall of 9,000 items (300 pages) per query regardless of how many it says exist. The summary row reports the gap.

## `extraFilters` (type: `object`):

Raw subito query parameters for category-specific filters, e.g. {"fl":"2"} for diesel or {"gr":"2"} for automatic. These are passed through UNVERIFIED — subito silently ignores names it does not recognise — so the run also fetches the same search without them and reports both totals in `extraFiltersChangedTotal`, letting you see whether your filter did anything.

## `maxConcurrency` (type: `integer`):

Page fetches in flight at once across all queries.

## `minRequestInterval` (type: `integer`):

Politeness pacing shared across all workers.

## `proxyConfiguration` (type: `object`):

Optional and OFF by default. DataDome is present on the domain but never fired during recon; an Italian or European residential proxy is the first thing to try if it ever does.

## Actor input object example

```json
{
  "categories": [
    "auto"
  ],
  "regions": [
    "italia"
  ],
  "query": "bmw",
  "titleOnly": false,
  "advertiserType": "any",
  "sortOrder": "default",
  "maxItemsPerQuery": 120,
  "extraFilters": {},
  "maxConcurrency": 3,
  "minRequestInterval": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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": [
        "auto"
    ],
    "regions": [
        "italia"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/subito-classifieds-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": ["auto"],
    "regions": ["italia"],
}

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/subito-classifieds-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": [
    "auto"
  ],
  "regions": [
    "italia"
  ]
}' |
apify call scrapyx/subito-classifieds-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapyx/subito-classifieds-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/Fl2QpgKuVuL10us0m/builds/pBQrW1sqwRtbE5Nvx/openapi.json
