# Tori.fi Scraper — Finland Marketplace Listings & Prices (`logiover/tori-fi-marketplace-scraper`) Actor

Scrape Tori.fi, Finland's largest online marketplace. Extract title, price in euros, brand, item condition, availability, city, district and region, listing age, ad type and images across every category. Keyword, category and price filters. No API key, no login.

- **URL**: https://apify.com/logiover/tori-fi-marketplace-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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/platform/actors/running/actors-in-store#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

## Tori.fi Scraper — Finland Marketplace Listings, Prices & Locations

Finland's largest marketplace in rows: price in euros, brand, item condition, availability, and the city, district and region each item sits in.

### What does the Tori.fi Scraper do?

This Actor collects live listings from **Tori.fi**, the marketplace where Finland buys and sells second-hand. Each result page carries its listings twice — as cards in the DOM and as JSON-LD Product objects — and neither is complete on its own. The cards know where an item is and how long it has been listed; the JSON-LD knows its condition and availability. This Actor reads both and joins them on the listing ID, so one row carries the whole picture.

Search by keyword, browse one of the marketplace's categories, or do both, optionally with a price range, then choose a sort order. The Actor pages through about 52 listings per page writing one flat row each: title, euro price, brand, condition, availability, the location string split into city, district and region, how long ago it was posted, and the photo.

### Who is it for?

- **Resellers and arbitrage traders** watching Finnish second-hand prices for under-priced stock.
- **Market researchers** measuring resale values in one of Europe's most active circular-economy markets.
- **Retail and brand teams** tracking how their products hold value after the first sale.
- **Marketplace operators** benchmarking supply and pricing in the Nordics.
- **Logistics and local-services businesses** mapping where supply concentrates by region.

### Use cases

- Track the resale price of a phone or bike model over time and build a depreciation curve.
- Compare asking prices between Helsinki, Tampere and Oulu using the parsed city and region fields.
- Filter by condition to separate new-in-box listings from genuinely used stock.
- Watch a category daily and catch new listings within minutes of posting.
- Size regional supply for a category to decide where to open a pickup point.
- Feed an AI agent live Finnish resale prices for valuation questions.

### Why use this Tori.fi Scraper?

- **Location parsed into city, district and region**, not left as one unsplit string.
- **Condition and availability from JSON-LD**, joined onto the card data rather than guessed from the title.
- **About 52 listings per page**, with pagination that keeps returning new items.
- **Category browsing and keyword search**, together or separately.
- **Keyless and login-free** — nothing to register, nothing to rotate.
- **Prices as euros**, cleanly parsed from the card label.

### What data can you extract?

One row per listing. Anything the source left blank comes back as `null`.

| Field | Type | Description |
|---|---|---|
| `listingId` | string | Tori listing identifier |
| `url` | string | Direct link to the listing |
| `title` | string | Listing title |
| `price` | number | Asking price in euros |
| `currency` | string | Currency, normally EUR |
| `brand` | string | Brand where Tori recorded one |
| `condition` | string | Item condition, e.g. Used or New |
| `availability` | string | Availability, e.g. In Stock |
| `city` | string | City or municipality |
| `district` | string | District or neighbourhood where given |
| `region` | string | Region (maakunta) |
| `locationText` | string | Location exactly as displayed |
| `postedText` | string | How long ago it was posted, e.g. "48 min" or "20.7." |
| `category` | string | Category requested |
| `imageUrl` | string | Listing photo |
| `scrapedAt` | string | When this row was collected |

#### Sample output

```json
{
  "listingId": "45104150",
  "url": "https://www.tori.fi/recommerce/forsale/item/45104150",
  "title": "tukkuerä panssarilaseja",
  "price": null,
  "currency": null,
  "brand": null,
  "condition": null,
  "availability": null,
  "adType": null,
  "city": "Tuusula",
  "district": "Hyrylä",
  "region": "Uusimaa",
  "locationText": "Tuusula, Hyrylä, Uusimaa",
  "postedText": "4 pv",
  "category": "All categories",
  "imageUrl": "https://img.tori.net/dynamic/default/item/45104150/e1d1915e-5e5e-4347-98d9-c7d06fb77229",
  "scrapedAt": "2026-08-15T07:59:22.830Z"
}
```

### How to use the Tori.fi Scraper

#### Option A — a keyword search

Enter a term such as `iphone`, `polkupyörä` or `sohva`, sort by newest first and set a result limit. Finnish and English both work; Finnish returns more.

#### Option B — a whole category

Leave the keyword empty and pick a category — vehicles, home & living, electronics, leisure, fashion, property and more. This is the way to build a broad dataset of what Finland is selling right now.

#### Option C — a price band

Add a minimum and maximum price to isolate a segment, then schedule the run and diff between days to catch new supply as it appears.

### Input parameters

| Input | Type | Description |
|---|---|---|
| `query` | string | What to search for, e.g. iphone, polkupyörä, sohva. Leave empty to browse a whole category. Default: `"iphone"`. |
| `category` | string | Optional Tori category to browse. Combine with a keyword to narrow it. |
| `priceFrom` | integer | Optional lower price bound. |
| `priceTo` | integer | Optional upper price bound. |
| `sortBy` | string | Order the results before collecting them. Default: `"PUBLISHED_DESC"`. |
| `maxResults` | integer | Stop after this many listings. Each page returns about 52. Default: `500`. |
| `proxyConfiguration` | object | Tori serves Finnish exits. Residential proxy pinned to Finland is used automatically. |

### Tips for best results

- Sorting by newest first and running on a schedule is the most reliable way to catch listings before they sell — good stock on Tori moves in hours.
- `postedText` is relative, exactly as Tori displays it: minutes and hours for today, a date for older listings.
- A two-part location means the item has no separate district; `city` and `region` are still filled correctly.
- Finnish keywords return substantially more than English ones for household categories.
- Brand is filled for roughly nine listings in ten in electronics, and far less in categories where sellers do not name one.

### Integrations

Connect this Actor to Make, Zapier, n8n, Slack, Google Sheets, GitHub, Airtable or any HTTP endpoint through Apify integrations. Every finished run can push its dataset straight into your warehouse, or fire a webhook so a downstream job starts the moment the data lands.

### API usage

Run the Actor from your own code with the Apify API. Datasets can be exported as JSON, CSV, Excel, XML, RSS or HTML, and every run is available through the [Apify API reference](https://docs.apify.com/api/v2).

```bash
curl -X POST "https://api.apify.com/v2/acts/logiover~tori-fi-marketplace-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"input": {"query": "iphone", "category": "", "sortBy": "PUBLISHED_DESC", "maxResults": 1000, "proxyConfiguration": {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "FI"}}}'
```

Python, JavaScript, PHP and CLI clients are documented under [Apify API clients](https://docs.apify.com/api/client).

### Use with AI agents (MCP)

This Actor is callable from any MCP-compatible client — Claude, Cursor, VS Code or your own agent — through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). An agent can call it to answer live questions about Finnish second-hand prices, regional supply and item condition instead of guessing from stale training data.

### FAQ

#### Do I need a Tori account or API key?

No. The Actor reads public listings with no login and no key.

#### How many listings can one run return?

Tori carries hundreds of thousands of live listings. About 52 arrive per page and pagination keeps producing new ones, so the practical limit is the result cap you set.

#### Can I get the seller's contact details?

No. Tori keeps contact behind its own message flow, and this Actor does not attempt to reach it.

#### What does the category code mean?

Tori identifies its sections with codes such as `0.93` for vehicles. The input presents them as readable names, so the codes never have to be typed.

#### Why is the price sometimes missing?

A small share of listings are posted without a price — usually wanted ads or free items. The row still carries everything else.

#### Is the data in Finnish?

Yes. Titles, locations and categories are published in Finnish and collected as written.

#### Why did my run return zero listings?

Usually a keyword and price range that exclude each other. Clear the price range first.

#### How fresh is `postedText`?

It is read at run time, so "48 min" means 48 minutes before the run, not before you read the file. `scrapedAt` gives you the anchor.

#### Can I export to CSV or Excel?

Yes. Every run's dataset exports as JSON, CSV, Excel, XML, RSS or HTML from the Storage tab, the API, or automatically through an integration.

#### How fresh is the data?

Every run reads the site live at that moment, so the data is as fresh as the site itself. Schedule the Actor hourly, daily or weekly to build a time series.

#### How often is the Actor updated?

It is monitored and fixed when the site changes its markup or its endpoints. Report anything that looks wrong through the Issues tab and it gets picked up.

### Is it legal to scrape Tori.fi?

This Actor collects only publicly available information — the same pages any visitor can open without logging in. It does not bypass a login, and it does not touch private or personal accounts. Public data collection is legal in most jurisdictions, but how you *use* the data is your responsibility: if any record contains personal data, GDPR and comparable laws still apply, and you need a lawful basis for processing it. When in doubt, take legal advice. See Apify's [ethical web scraping](https://blog.apify.com/what-is-ethical-web-scraping-and-how-do-you-do-it/) guide.

### Related scrapers

- [Blocket Scraper](https://apify.com/logiover/blocket-se-scraper) — Swedish classifieds.
- [Finn.no Scraper](https://apify.com/logiover/finn-no-scraper) — Norwegian marketplace.
- [DBA.dk Scraper](https://apify.com/logiover/dba-dk-scraper) — Danish classifieds.
- [Etuovi Scraper](https://apify.com/logiover/etuovi-scraper-finland-real-estate) — Finnish property listings.
- [Kleinanzeigen Scraper](https://apify.com/logiover/kleinanzeigen-de-classifieds-scraper) — German classifieds.

# Actor input Schema

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

What to search for, e.g. iphone, polkupyörä, sohva. Leave empty to browse a whole category.

## `category` (type: `string`):

Optional Tori category to browse. Combine with a keyword to narrow it.

## `priceFrom` (type: `integer`):

Optional lower price bound.

## `priceTo` (type: `integer`):

Optional upper price bound.

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

Order the results before collecting them.

## `maxResults` (type: `integer`):

Stop after this many listings. Each page returns about 52.

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

Tori serves Finnish exits. Residential proxy pinned to Finland is used automatically.

## Actor input object example

```json
{
  "query": "iphone",
  "category": "",
  "sortBy": "PUBLISHED_DESC",
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FI"
  }
}
```

# Actor output Schema

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

Every record collected in this run. Open the Dataset tab to browse, filter or export as JSON, CSV or Excel.

# 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 = {
    "query": "iphone",
    "category": "",
    "sortBy": "PUBLISHED_DESC",
    "maxResults": 500,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "FI"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/tori-fi-marketplace-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 = {
    "query": "iphone",
    "category": "",
    "sortBy": "PUBLISHED_DESC",
    "maxResults": 500,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "FI",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/tori-fi-marketplace-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 '{
  "query": "iphone",
  "category": "",
  "sortBy": "PUBLISHED_DESC",
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FI"
  }
}' |
apify call logiover/tori-fi-marketplace-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,logiover/tori-fi-marketplace-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/1lJlDZLJamIWqI8jW/builds/yKOVdELbJriSu4ufq/openapi.json
