# Tutti Scraper (`ivanvs/tutti-scraper`) Actor

Extract data from classified advertisements on tutti.ch. Scrape details from jobs, furniture, sports items, services, cars, trucks and more. Download listings data in JSON, XML, Excel, CSV and other formats. Unlimited and extremely fast!

- **URL**: https://apify.com/ivanvs/tutti-scraper.md
- **Developed by:** [Gen First](https://apify.com/ivanvs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 ad listings

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

## Tutti.ch Scraper

Extract listings, prices, descriptions, specifications, photos, locations, and seller details from
[tutti.ch](https://www.tutti.ch/), one of Switzerland's most popular classifieds sites. Paste a
tutti.ch search, seller, or ad URL and get clean, structured JSON that you can export to CSV, Excel,
JSON, XML, or HTML Table. No login, no cookies, and no proxy setup required.

### Quick facts

|                 |                                                                       |
| --------------- | --------------------------------------------------------------------- |
| Website         | `https://www.tutti.ch` (languages `de`, `fr`, `it`)                   |
| Accepted input  | Search URLs, keyword search URLs, seller (shop) URLs, single ad URLs  |
| Output          | One JSON record per listing, in the run's default dataset             |
| Pagination      | Automatic, up to 3,030 listings per search or seller URL              |
| Limit           | `maxRecords` (default `100`) caps the total number of records per run |
| Proxy           | Nothing to configure                                                  |
| Login / cookies | Not required                                                          |

### What does Tutti.ch Scraper do?

- 🔎 **Scrapes search results** — paste any tutti.ch search URL, with all your filters and sorting, and collect every listing in it. Pages are followed automatically.
- 🔤 **Scrapes keyword searches** — search by free text with `https://www.tutti.ch/de/q?query=<keyword>`.
- 🏪 **Scrapes seller and shop pages** — paste a seller profile URL and collect every ad that seller has published.
- 📄 **Scrapes individual ads** — paste a single ad URL to get its full record.
- 🚗 🛋️ 📱 **Works in every category** — cars, motorbikes, furniture, electronics, fashion, pets, and more.
- 🧾 **Returns rich data** — title, description, price in CHF, photos, location with coordinates, category, item specifications, and seller profile.
- 📤 **Export anywhere** — JSON, CSV, Excel, XML, or HTML Table, or read results through the Apify API.

### About tutti.ch

tutti.ch is a Swiss online marketplace for classified ads, available in German, French, and
Italian. Private sellers and businesses list everything from cars and bikes to furniture,
electronics, clothing, and pets. Prices are in Swiss francs (CHF).

### What can you do with this data?

- **Price monitoring** — track asking prices for a category, brand, or model over time.
- **Market research** — compare supply and prices across cantons, categories, or sellers.
- **Competitor and dealer tracking** — follow every ad a specific seller or shop publishes.
- **Lead generation** — find active sellers in a niche.
- **Dataset building** — feed structured listings into analytics, dashboards, or ML pipelines.

### How to use Tutti.ch Scraper

1. Open tutti.ch in your browser, run a search (add any filters and sorting you need), or open a seller profile or an ad.
2. Copy the URL from the address bar.
3. Paste it into the **urls** field. Add as many URLs as you like; you can mix types.
4. Set **maxRecords** to the maximum number of records you want (default `100`).
5. Click **Start**.
6. Download the results as JSON, CSV, Excel, XML, or HTML Table.

#### Input parameters

| Parameter    | Type    | Required | Default | Description                                                                    |
| ------------ | ------- | -------- | ------- | ------------------------------------------------------------------------------ |
| `urls`       | array   | yes      | —       | tutti.ch URLs to scrape. Each item is an object: `{ "url": "<tutti.ch URL>" }` |
| `maxRecords` | integer | no       | `100`   | Maximum number of records saved in the run, across all URLs. Minimum `1`.      |

Input format:

```json
{
  "urls": [{ "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA" }],
  "maxRecords": 100
}
```

Rules:

- Every URL must start with `https://www.tutti.ch/`. Other forms, such as `https://tutti.ch/...` or `http://...`, are ignored.
- `<lang>` in the URL patterns below is `de`, `fr`, or `it`. Listing text stays in the language the seller wrote it in.
- A CSV file or Google Sheet must list one URL per row in the first column. A Google Sheet must be shared as "Anyone with the link can view".
- A listing found through several URLs with the same `<lang>` is scraped only once.

#### Supported input URLs

| URL type       | Pattern                                             | Example                                                                                    |
| -------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Search         | `https://www.tutti.ch/<lang>/q/<slug>/<token>`      | `https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA` |
| Keyword search | `https://www.tutti.ch/<lang>/q?query=<keyword>`     | `https://www.tutti.ch/de/q?query=velo`                                                     |
| Seller / shop  | `https://www.tutti.ch/<lang>/seller?id=<seller-id>` | `https://www.tutti.ch/de/seller?id=8574745325378283257`                                    |
| Single ad      | `https://www.tutti.ch/<lang>/vi/<ad-id>`            | `https://www.tutti.ch/de/vi/83475620`                                                      |

Copy URLs straight from your browser's address bar. The filters, sorting, and page you chose on
tutti.ch are kept.

#### Unsupported URLs

These URLs are skipped and a warning is written to the run log:

- Category pages, such as `https://www.tutti.ch/de/cat/...`.
- Search URLs without the code at the end, such as `https://www.tutti.ch/de/q/autos-audi`. Apply a filter on tutti.ch and copy the new URL.
- Seller URLs without a numeric `id`.
- English paths (`/en/...`) and the home page.

#### Limits

- Search and seller URLs return 30 listings per page and are followed for up to 101 pages, so one URL yields at most **3,030 listings**. For bigger result sets, split the search into narrower ones (by category, canton, or price range) or add the same search with a different sort order.
- `maxRecords` counts every saved record, including "not found" records (see the FAQ).

### Examples

#### Input

Collect the 50 cheapest listings from a search:

```json
{
  "urls": [{ "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA?sorting=cheapest" }],
  "maxRecords": 50
}
```

Collect up to 500 newest ads from one seller:

```json
{
  "urls": [{ "url": "https://www.tutti.ch/de/seller?id=8574745325378283257" }],
  "maxRecords": 500
}
```

Scrape one ad:

```json
{
  "urls": [{ "url": "https://www.tutti.ch/de/vi/83475620" }],
  "maxRecords": 1
}
```

Mix a keyword search, a seller, and a single ad in one run:

```json
{
  "urls": [
    { "url": "https://www.tutti.ch/fr/q?query=velo&sorting=newest" },
    { "url": "https://www.tutti.ch/de/seller?id=8574745325378283257" },
    { "url": "https://www.tutti.ch/it/vi/83475620" }
  ],
  "maxRecords": 200
}
```

#### Output

Every URL type produces the same kind of record: one full listing per ad. The example below is
illustrative; personal details are replaced with placeholders and the lists are shortened.

```json
{
  "id": "12345678",
  "url": "https://www.tutti.ch/de/vi/12345678",
  "title": "Subaru Forester 2.5 XT",
  "description": "Gepflegter Subaru Forester mit Panoramadach und Anhängerkupplung.\nAb Platz.",
  "language": "DE",
  "price": 4500,
  "priceText": "4'500.-",
  "currency": "CHF",
  "images": ["https://c.tutti.ch/big/1111111111.jpg", "https://c.tutti.ch/big/2222222222.jpg"],
  "location": {
    "postalCode": "3000",
    "city": "Bern",
    "canton": "Bern",
    "cantonCode": "BE",
    "street": null,
    "latitude": 46.948,
    "longitude": 7.4474
  },
  "category": ["Fahrzeuge", "Autos"],
  "categoryId": "cars",
  "attributes": {
    "Marke": "SUBARU",
    "Modell": "FORESTER",
    "Erstzulassung": "2008",
    "Kilometerstand": "150000",
    "Treibstoff": "Benzin",
    "Getriebeart": "Automatik"
  },
  "seller": {
    "id": "1234567890123456789",
    "name": "Example Seller",
    "type": null,
    "profileUrl": "https://www.tutti.ch/de/seller?id=1234567890123456789",
    "memberSince": "2018-09-17T16:03:29Z",
    "websiteUrl": null,
    "logoUrl": null,
    "location": null,
    "subscription": null
  },
  "source": "tutti",
  "externalUrl": null,
  "highlighted": false,
  "publishedAt": "2026-10-12T01:05:25+02:00",
  "scrapedAt": "2026-10-15T08:30:00.000Z",
  "inputUrl": "https://www.tutti.ch/de/vi/12345678"
}
```

### Output formats

Results are saved to the run's default dataset. When the run finishes, download them as **JSON,
CSV, Excel, XML, or HTML Table**, or read them through the Apify API.

### ❓ FAQ

#### Do I need proxies to scrape tutti.ch?

No, there is no proxy setting in the input.

#### Do I need to write code?

No. Paste your URLs, set `maxRecords`, and click **Start**.

#### Can I scrape a whole search or just one ad?

Both. A search URL collects every listing in the results; an ad URL collects one listing. You can
mix search, keyword search, seller, and ad URLs in the same `urls` list.

#### Can I scrape every ad from one seller or shop?

Yes. Paste the seller's profile URL, for example `https://www.tutti.ch/de/seller?id=8574745325378283257`.
The actor goes through all of the seller's ads, up to `maxRecords` and the 3,030-listing limit.

#### How many listings can I scrape?

Set the total with `maxRecords` (default `100`). One search or seller URL returns at most 3,030
listings; split large searches into narrower ones to collect more.

#### How do I scrape many URLs at once?

Add them all to `urls`, or put them in a CSV file or Google Sheet (one URL per row, first column)
and add `{ "requestsFromUrl": "<link>" }` to `urls`.

#### How do I know which input produced a record?

Every record has an `inputUrl` field set to the URL you supplied.

#### What if an ad, search, or seller has no data?

The actor still saves a record so that gaps are visible:

- An ad that no longer exists: `{ "inputUrl": "...", "url": "...", "title": "AD not found" }`.
- A search with no results: `{ "inputUrl": "...", "url": "...", "title": "No results found" }`.
- A seller id that does not exist: `{ "inputUrl": "...", "url": "...", "title": "Seller not found" }`.

#### Is it legal to scrape tutti.ch?

Scraping publicly available data is generally permitted, but you are responsible for how you use
it. Listings can contain personal data, such as seller names, which is protected by the Swiss
Federal Act on Data Protection (FADP) and, where it applies, the GDPR. Collect only what your use
case needs, follow tutti.ch's terms, and consult a lawyer if you are unsure.

#### What export formats are available?

JSON, CSV, Excel, XML, and HTML Table, plus programmatic access through the Apify API.

### Support

For custom or simplified outputs, or to report a bug, contact the developer at
**support (at) getmediumdata.com** or open an issue.

# Changelog

This Actor's version history is a separate document: https://apify.com/ivanvs/tutti-scraper/changelog.md

# Actor input Schema

## `maxRecords` (type: `integer`):

Maximum number of records to be scraped

## `urls` (type: `array`):

List of URLs from Tutti.ch (https://tutti.ch/) that needs to be scraped — search result pages, shop pages or single ad pages

## Actor input object example

```json
{
  "maxRecords": 10,
  "urls": [
    {
      "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA"
    }
  ]
}
```

# Actor output Schema

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

No description

# 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 = {
    "maxRecords": 10,
    "urls": [
        {
            "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ivanvs/tutti-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 = {
    "maxRecords": 10,
    "urls": [{ "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA" }],
}

# Run the Actor and wait for it to finish
run = client.actor("ivanvs/tutti-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 '{
  "maxRecords": 10,
  "urls": [
    {
      "url": "https://www.tutti.ch/de/q/autos-audi/Ak8CkY2Fyc5SRkrJjYXJzQXV0b1Njb3V0QnJhbmSkYXVkacDAwA"
    }
  ]
}' |
apify call ivanvs/tutti-scraper --silent --output-dataset

```

## MCP server setup

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