Tori.fi Scraper
Pricing
from $2.40 / 1,000 results
Tori.fi Scraper
Tori.fi is where most of Finland's second-hand supply sits, a thin market of five and a half million people where good listings don't stay up long, and it prices in euros like the rest of the eurozone. Rows give price, locality, trade type and a retailer-or-private flag. No seller data collected.
Pricing
from $2.40 / 1,000 results
Rating
0.0
(0)
Developer
Lowland Data
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
9 days ago
Last modified
Categories
Share
Finland is the one Nordic country that prices in euros, so Tori.fi rows drop into a eurozone dataset without an exchange-rate step. Tori is also where most of Finland's second-hand supply sits, and that supply is thin: five and a half million people, and good listings do not stay up long.
This actor takes a Finnish search term and returns matches as structured rows, with the price in whole euros, locality, trade type, posting timestamp, the seller's spec picks such as brand and condition, the site's own badges, photos at full resolution, and a retailer or private flag. A posting-date window means a daily run can ask only for what appeared since yesterday.
It runs, every time, and you can check that before you spend anything. lowlanddata.com/status/tori-fi-scraper is this actor's public health record: every run of the last 30 days, the success rate, the daily canary, failures included. Full input/output reference on the tool page.
No login, no CAPTCHA solving, no private endpoints. The actor reads what Tori.fi shows a logged-out visitor, paces its requests and stays on standard datacenter proxies - which is also why a scoped run finishes in seconds.
Quick start (30 seconds)
- Put what you'd type in the Tori.fi search box into searchQuery, e.g.
polkupyörä. - Click Start. That's the whole minimum setup.
- When the run finishes, open the dataset's Overview tab for a clean table, or Export it as CSV/Excel/JSON.
Optional knobs: a price band in euros and newest-first sorting for monitoring, and any input works on a daily Schedule.
What you can build with it
- Watch a niche for underpriced listings. Run
searchQuery: "el-polkupyörä"withpriceMax: 1500andsortBy: "date"hourly: every new listing arrives withpriceAmountparsed and give-aways (priceAmount: 0) included. - Map second-hand prices by locality. Every listing carries its
city: chart what the same bike costs in Helsinki versus Tampere without touching a coordinate. - Track retailer vs. private supply. The
sellerTypeflag tells you how much of any category is professional traders: market structure no Tori.fi page shows you. - Filter by brand without opening a listing.
attributescarries the seller's spec picks - brand, condition, whatever the category offers - so a brand filter is one column, not a title search. - Feed an AI agent or a pipeline. Every field is structured and predictable, and the site's nested data is flattened to plain columns, so an assistant can consume it directly with no parsing step.
What you get
Each listing is one dataset item:
{"listingId": "474000001","url": "https://www.tori.fi/recommerce/forsale/item/474000001","title": "Lasten polkupyörä 20 tuumaa","priceAmount": 600,"currency": "EUR","postedAt": "2026-08-21T06:06:40.000Z","city": "Jyväskylä","tradeType": "Myydään","sellerType": "private","attributes": { "brand": "Trek" },"labels": ["private"],"imageUrl": "https://images.tori.fi/dynamic/default/item/474000001/original","imageUrls": ["https://images.tori.fi/dynamic/default/item/474000001/sized"],"description": "Lasten polkupyörä, 20 tuumaa. Hyväkuntoinen, vähän ajettu.","adId": "474000001","adType": 67,"listingType": "bap"}
Field notes, so you know exactly what you are buying:
priceAmountis in whole euros;0covers give-away listings. Listings without a price carry no amount.descriptionis the seller's full free-text description, read from the listing's own page. It appears only when Fetch descriptions (scrapeDetails) is on - the search results do not carry it. The seller-profile section is never read, so no name or profile contact reaches the output.tradeTypeis the site's own label for the ad type: for sale, give-away or wanted ad.attributesis whatever the seller picked from the category's spec fields, one key per spec. Which keys appear depends on the category - a bike hasbrand, a phone hasmodel. Absent when the seller picked nothing.labelsare the site's own badges by id:retailerorprivate, plus the shipping and buy-now badges where a listing carries them.imageUrlis the original photo;imageUrlsthe sized variants the site serves, up to eight.cityis locality-level. Seller names, shop names and map coordinates are not collected.postedAtreflects publication or the seller's last bump.adId,adTypeandlistingTypeare Tori.fi's own identifiers, for anyone reconciling against the site.
How much does it cost to scrape Tori.fi?
$3.00 per 1,000 listings delivered, pay-as-you-go, no subscription, and you pay per result rather than per hour. A run that finds nothing still costs the $0.005 actor start. In plain dollars:
- 100 listings ≈ $0.30, a daily niche watch.
- 500 listings ≈ $1.50, a solid market snapshot.
- A 2,500-listing crawl ≈ $7.50, a full query window, deduplicated.
The price is all-inclusive: your runs' platform usage is covered by it, with no separate compute or proxy charges. Runs are fast. A scoped few-hundred-item run typically finishes in under ten seconds. Datacenter proxies are sufficient, no residential proxy surcharge needed.
Free-plan runs are limited to a sample of 5 items, enough to evaluate the output format against your real query.
Not technical? Let your AI assistant set it up
Copy this into ChatGPT, Claude or any AI assistant, fill in the one line, and follow the conversation:
Help me set up the "Tori.fi Scraper" actor on Apify(https://apify.com/lowlanddata/tori-fi-scraper). Guide me one step at a time.What I want to watch: [E.G. "electric bikes under 1,500 euros"]Guide me to:1. Propose my input values: searchQuery (what I'd type in the Tori.fi search box),an optional priceMin/priceMax band in euros, sortBy "date" for newest-firstmonitoring, and maxItems.2. Create a free Apify account (apify.com), open the actor page, paste the valuesinto the Input form, and start a run.3. Set up a daily Schedule in the Apify Console with the same input, plus an emailor Slack integration so new results reach me automatically.4. Show me how to export results as CSV/Excel, or read them from the API if I code.5. If the results are what I wanted, remind me at the end to leave a quick rating on the actor page, and to report anything broken or missing on its Issues tab.
Input
| Field | Description |
|---|---|
searchQuery | What you'd type in the Tori.fi search box. Required. |
priceMin | Only listings costing at least this many euros. |
priceMax | Only listings costing at most this many euros. |
sortBy | date (newest first, default), price_asc, price_desc, or relevance. |
postedAfter | Only listings posted on or after this date (YYYY-MM-DD). Stops early with newest-first sorting. |
postedBefore | Only listings posted on or before this date (YYYY-MM-DD). |
maxItems | Stop after this many listings (default 1000). |
scrapeDetails | Read each listing's own page for the seller's full description (default off). One extra request per listing. |
proxyConfiguration | Proxy settings; keep Apify proxy enabled. |
A run minimally needs a searchQuery; invalid combinations (like an inverted price band) fail immediately with the reason in the run's status message.
Use it from your code
Run the actor and get items straight back with one HTTP call (fine for scoped runs up to ~5 minutes):
curl "https://api.apify.com/v2/acts/lowlanddata~tori-fi-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \-X POST -H "Content-Type: application/json" \-d '{"searchQuery": "polkupyörä", "maxItems": 100}'
Node.js:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });const run = await client.actor('lowlanddata/tori-fi-scraper').call({searchQuery: 'polkupyörä',maxItems: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("lowlanddata/tori-fi-scraper").call(run_input={"searchQuery": "polkupyörä", "maxItems": 100})items = client.dataset(run["defaultDatasetId"]).list_items().items
For bigger crawls, start the run asynchronously and fetch the dataset when the finished-run webhook fires. Schedules (e.g. a daily price snapshot), webhooks and the Make/Zapier/n8n integrations all work out of the box. This is a standard Apify actor.
Use it with AI agents (MCP)
Claude, Cursor and other MCP-capable agents can run this scraper as a tool through Apify's hosted MCP server: the agent fills in the search itself, starts the run and reads the results, no glue code.
Claude Code:
$claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/tori-fi-scraper"
Cursor or Claude Desktop (add a custom connector / MCP server with this URL):
https://mcp.apify.com?actors=lowlanddata/tori-fi-scraper
Want the whole family at once? Point one connector at every tool in the EU Marketplaces bundle:
https://mcp.apify.com?actors=lowlanddata/kleinanzeigen-scraper,lowlanddata/marktplaats-scraper,lowlanddata/tweedehands-scraper,lowlanddata/olx-pl-scraper,lowlanddata/olx-ro-scraper,lowlanddata/olx-pt-scraper,lowlanddata/willhaben-scraper,lowlanddata/finn-no-scraper,lowlanddata/tori-fi-scraper,lowlanddata/blocket-se-scraper,lowlanddata/dba-dk-scraper,lowlanddata/gumtree-uk-scraper,lowlanddata/vinted-scraper,lowlanddata/bol-com-scraper,lowlanddata/subito-scraper,lowlanddata/bazos-cz-scraper,lowlanddata/bazos-sk-scraper,lowlanddata/olx-bg-scraper,lowlanddata/olx-ua-scraper,lowlanddata/willhaben-car-scraper,lowlanddata/kleinanzeigen-free-finds,lowlanddata/olx-listing-watch,lowlanddata/marktplaats-new-listing-alerts,lowlanddata/tweedehands-new-listing-alerts,lowlanddata/kleinanzeigen-deal-radar
Sign in with your Apify account when prompted. Runs are billed to it. Setup details per client: Apify MCP docs, or start from this actor's own MCP page: apify.com/lowlanddata/tori-fi-scraper/api/mcp.
Prompts that work once connected:
- "Search Tori.fi for 'el-polkupyörä' under 1,500 euros and summarize the price distribution."
- "Get the 100 newest 'iphone 15' listings from Tori.fi and flag private sellers below the median price."
- "Watch Tori.fi for 'kajakki' and tell me when something under 300 euros appears."
Beyond the ~2,600-result window
Tori.fi serves at most 50 pages per query (about 2,650 listings). The run reports honestly when a query is bigger than its window. Split broad queries by price bands (priceMin/priceMax) across runs; overlapping runs merge cleanly on listingId.
Is it legal to scrape Tori.fi?
Listing prices, titles and localities are public commercial information. This actor reads what Tori.fi shows any logged-out visitor, never signs in, bypasses no anti-bot protection, and paces its requests so its load on the site is negligible. It does not collect seller names, shop names or map coordinates; the only seller-derived field is whether a listing comes from a retailer or a private person. Titles are the seller's own words, delivered as-is.
Finland applies the GDPR, supervised by the Office of the Data Protection Ombudsman (Tietosuojavaltuutetun toimisto). How you store and use the data once it is yours is governed by the law of your own jurisdiction.
This actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Tori.fi or its owners, and trademarks belong to their respective holders.
Is there a Tori.fi API alternative?
Tori.fi's public API programme is aimed at partners, not ad-hoc listing search. This actor is the practical alternative: the same listings as structured JSON through one HTTP call (run-sync-get-dataset-items), on a schedule, or as an MCP tool for AI agents.
Does Tori.fi block scrapers?
This actor makes ordinary requests: paced, on standard datacenter proxies, load kept negligible. No CAPTCHA fights, no bot-wall cat-and-mouse, which is also why runs are fast and reliable enough for daily schedules. The health record above shows how that holds up day to day.
How do I monitor Tori.fi prices?
Set sortBy: "date" with your query, cap maxItems to a page or two, and add a daily (or hourly) Schedule in the Apify Console with an email/Slack integration on the runs: every new listing lands in your inbox with the price already parsed. The AI-assistant prompt above walks a non-technical user through exactly this setup. Even tighter: set postedAfter to yesterday's date. The dataset then contains only the new listings, nothing to dedupe on your side.
FAQ
Can I get seller names or phone numbers? No. The output says whether the seller is a retailer or a private person, and nothing else about them.
Does it cover cars, boats and property? This actor searches the general-goods marketplace. Tori.fi's vehicle and property verticals carry different data, candidates for separate actors, done properly.
Can I get only the newest listings? Yes. Set postedAfter to a date (yesterday, say) and the dataset contains only listings posted since then. With newest-first sorting the run stops paging as soon as it provably reaches older listings, so a daily watch stays fast and cheap.
How fresh is the data? Live at run time. Every run queries Tori.fi directly. For continuous freshness, schedule the actor.
Can I export to Excel or CSV? Yes. Every dataset exports as CSV, Excel, JSON or XML from the Apify Console or API.
Does it work with Make, Zapier or n8n? Yes. It is a standard Apify actor; all platform integrations, webhooks and schedules apply.
Can I get Tori.fi data through an official API? Not as a self-serve product. Tori.fi's API programme is partner-oriented. This actor delivers the equivalent listing data as JSON on demand instead.
Is it GDPR-compliant to scrape Tori.fi? The output carries no seller name, shop name or precise location, only public commercial facts about the listing. Finland's Data Protection Ombudsman applies the same GDPR baseline as the rest of the EU; see the section above.
How is pricing calculated? Per delivered listing: 1,000 listings cost $3.00, with no minimum and no bill for runs that fail or return zero results.
What if my search has more than 2,650 results? That is Tori.fi's 50-page ceiling per query. Cover a larger market by running the search in euro price bands and joining the datasets on listingId.
Can I bulk-export Tori.fi listings? That is what a run is. Set maxItems to the size you need, up to the ~2,650-listing window per query, then export the dataset as CSV, Excel or JSON from the Console or read it over the API. Beyond one window, split by price band.
In what order do results arrive? Newest first by default. sortBy also offers price_asc, price_desc and relevance when you want a different cut.
How do I fetch only yesterday's listings? Put yesterday's date in postedAfter. The run stops paging as soon as it reaches older items, so the daily dataset stays small and cheap. postedBefore bounds the other end when you need a window.
Is there a way to spot professional sellers? sellerType labels each listing retailer or private, enough to measure trade supply in a category without identifying anyone.
How precise is the location data? Locality only, via city. Nothing finer is collected.
What is in attributes? The spec fields the seller filled in for that category - brand, condition, size, model - one key each, flattened so they land as ordinary columns in an export. Which keys appear depends entirely on the category and on what the seller picked.
What are labels? Tori.fi's own badges on the listing, by id: retailer or private, plus the shipping and buy-now badges where a listing carries them.
How long until I have results? For a scoped run of a few hundred items, usually seconds (under ten in typical runs), so a single blocking HTTP call is often all the code you need.
How many items can I pull in one go? maxItems sets the ceiling, 1,000 by default. Free Apify accounts get a 5-item sample per run.
Can I check the output before spending money? Yes. Run your real query on the free plan and inspect the 5-item sample it returns.
Are images part of the output? Yes. imageUrl is the original photo at full resolution; imageUrls is an array of the sized variants, up to eight.
Why do some listings cost 0? Those are give-aways: the actor keeps them with priceAmount: 0 instead of filtering them out, since free items are part of the market picture.
Can I plug this into an AI agent? Yes, over MCP: Apify's hosted MCP server exposes this actor as a tool that Claude, Cursor and similar agents can call directly. See the MCP section for the connection URL.
Why did a listing's date move forward? postedAt follows the seller's last bump as well as first publication, so re-promoted listings carry a fresh timestamp.
Related scrapers
Working the Nordic second-hand market? Same output discipline, same public health record:
- Blocket.se Scraper: Sweden's biggest marketplace.
- DBA.dk Scraper: Denmark's classifieds institution.
Troubleshooting
The actor fails fast with the reason in the run's status message:
- "priceMin must not be higher than priceMax.": swap the two values.
- "The site blocked the run before any results could be fetched. This is usually temporary - retry in a few minutes.": a temporary block on the first request; a retry usually lands on a clean proxy session.
- "... the site serves at most this many pages per query ...": the query is bigger than Tori.fi's result window; add a price band for full coverage.
- Fewer items than requested on a free plan: the 5-item free sample cap; run on a paid Apify plan for full results.
Support
Found an issue or missing a field you need? The fastest route is the actor's Issues tab - it is monitored and reports get fixed. For anything private, email contact@lowlanddata.com. This actor is actively maintained.
Working well for you? A rating on this page takes ten seconds and helps other buyers find it. It is also the clearest signal of what we should build next.


