# Blocket Ads Scraper (`axiomworks/blocket-ads-scraper`) Actor

Collect classified ads from Blocket’s general marketplace and return titles, prices, locations, seller type, images, publish times and ad URLs. Optional ad-page details include descriptions, category paths and condition. Uses Blocket’s JSON search endpoint without a browser.

- **URL**: https://apify.com/axiomworks/blocket-ads-scraper.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

## Blocket Ads Scraper

**Returns:** one row per Blocket ad with id, sourceUrl, title, price, currency, location, sellerType, postedAt.
**Input:** `{"queries": ["cykel"], "maxItems": 20, "includeDetails": false}`
**Best for:** second-hand price research, newest-ad monitoring feeds, comparing private and business sellers.

```json
{
  "id": "27370404",
  "sourceUrl": "https://www.blocket.se/recommerce/forsale/item/27370404",
  "title": "Cykel, ITERA Plastcykel från Vilhelmina Cykelfabrik",
  "price": 500,
  "currency": "SEK",
  "location": "Lycksele",
  "sellerType": "private",
  "postedAt": "2026-10-12T19:43:20.000Z"
}
```

### What does Blocket Ads Scraper do?

Blocket Ads Scraper collects classified ads from the general marketplace (Torget) on Blocket.se, Sweden's largest classifieds site. You give it one or more keywords, an optional category ID, or Blocket search URLs, and it returns one structured record per ad: title, asking price, currency, location, seller type, images, publish time, trade type and, if you ask for details, the description, category path and item condition.

The Actor reads the same JSON search endpoint that the Blocket website uses for its own result pages, so it is fast and does not need a browser. It pages through the results, removes duplicate ads, and stops exactly when your item limit is reached. No login is needed, and the Actor never touches private account data.

Typical uses:

Price research for second-hand goods such as bicycles, sofas, electronics or tools.

Tracking how many ads exist for a keyword, and how asking prices change over time.

Building a feed of newly published ads for a product category, using the newest-first sort order.

Comparing private sellers with businesses for a given item type.

Feeding listings into spreadsheets, dashboards, alerts or AI agents.

This Actor is an independent tool. It is not affiliated with, endorsed by or connected to Blocket.

### What data can you get?

Every record contains the fields below. Fields marked "details" are filled only when `includeDetails` is switched on, because they come from the individual ad page.

| Field | Type | Description |
|---|---|---|
| `id` | string | Blocket ad ID, unique within a run |
| `sourceUrl` | string | URL of the ad page |
| `title` | string | Ad heading |
| `price` | number | Asking price, null when the ad shows no price |
| `currency` | string | Currency code, for example SEK |
| `location` | string | Town or area shown on the ad |
| `sellerType` | string | `private` or `business` |
| `organisationName` | string | Business name when the seller is a business |
| `images` | array | Image URLs of the ad |
| `latitude` | number | Latitude of the ad location as given by Blocket, null if absent |
| `longitude` | number | Longitude of the ad location, null if absent |
| `postedAt` | string | ISO timestamp of the ad's latest publish time |
| `tradeType` | string | Trade type label, for example Säljes (for sale) |
| `description` | string | Structured-data description, or page description when structured data is absent (details) |
| `fullDescription` | string | Complete public seller description (details); null when unavailable |
| `category` | string | Category path, for example Sport och friluftsliv > Cykling > Cyklar (details) |
| `condition` | string | Item condition such as New or Used (details) |

Some notes on the data:

The seller's personal name is not exposed by the search endpoint, so the Actor only reports whether the seller is private or a business, plus the business name when one is shown.

The existing `description` field keeps Blocket's structured-data summary, which the site often shortens to roughly 160 characters. When that summary is absent, it falls back to the seller description on the public page. With `includeDetails: true`, `fullDescription` contains the complete public seller description, preserving paragraph breaks and decoding HTML entities. It excludes the expand button and accessibility instructions. Both fields are null when the page has no usable description or cannot be fetched. Missing condition and category values remain null; the Actor does not infer them from the description.

Ads without a price, for example ads marked as free or "contact seller", return `null` for `price` and `currency`.

The `postedAt` value is derived from the timestamp that Blocket returns in the search response.

### How to use Blocket Ads Scraper

1. Open the Actor in Apify Console and go to the Input tab.
2. Enter one or more keywords in **Search keywords**, for example `cykel` or `soffa`.
3. Optionally add a **Category ID** to narrow the search, or paste Blocket search URLs into **Start URLs**.
4. Optionally set **Minimum price**, **Maximum price** and **Seller type**. Choose a **Sort order** and set **Max items**.
5. Switch on **Include ad details** if you need description, category and condition.
6. Click Start. When the run finishes, open the Output tab and download the dataset as JSON, CSV, Excel or XML.

A search shows at most about 50 pages of roughly 50 ads each. To collect more than that for a broad topic, use several keywords or several categories, since every keyword is searched separately and duplicate ads are removed across all of them.

### Input

| Field | Type | Description |
|---|---|---|
| `queries` | array of strings | Keywords to search, for example `cykel`. Required unless you give startUrls or a category. |
| `category` | string | Optional category ID such as `0.91`, `1.91.3108` or `2.91.3108.362`. Empty means all categories. |
| `startUrls` | array | Search URL objects, e.g. `[{"url":"https://www.blocket.se/recommerce/forsale/search?q=cykel"}]`. URL parameters supply search filters; item URLs are not detail targets. |
| `location` | string | Blocket location ID; empty searches all Sweden. For example, `0.300001` restricts to Stockholm county. A URL `location` value takes precedence. |
| `publishedToday` | boolean | Default false. True uses Blocket’s published-today filter; a URL `published=1` enables it and another explicit value disables it. |
| `minPrice` | integer | Optional lower price limit in SEK, applied by Blocket's search. Also read from `price_from` in a start URL. |
| `maxPrice` | integer | Optional upper price limit in SEK. Also read from `price_to` in a start URL. |
| `sellerType` | string | `any` (default), `private` or `business`. Applied after fetching, so a rare seller type may need more pages. |
| `sort` | string | `RELEVANCE` (default), `PRICE_ASC`, `PRICE_DESC` or `PUBLISHED_DESC`. |
| `maxItems` | integer | Maximum ads to save in total, 1 to 5000, default 50. |
| `includeDetails` | boolean | Fetch each ad page for description, category and condition. Default false. |
| `proxyConfiguration` | object | Apify Proxy settings. No proxy by default; the Actor falls back to a datacenter proxy if direct requests are blocked. |

The item limit is shared across all queries and URLs, with duplicate IDs saved once. URL location, published-today and price filters override the matching input options; an absent URL sort uses `sort`. If no results are saved, try broader keywords, clear the category or price bounds, set `sellerType` to `any`, or supply a Torget search URL. For repeated HTTP blocks, configure `proxyConfiguration` and retry. An unavailable detail page leaves its detail fields null.

Example input:

```json
{
  "queries": ["cykel"],
  "sort": "PUBLISHED_DESC",
  "maxItems": 100,
  "includeDetails": true
}
```

Category IDs follow Blocket's own hierarchy: IDs starting with `0.` are top-level categories, `1.` are sub categories and `2.` are product categories. You can find an ID by applying a category filter on Blocket.se and reading the `category` parameter in the address bar, then pasting that URL into Start URLs.

For a regional monitoring feed, use `{"queries":["cykel"],"location":"0.300001","publishedToday":true,"sort":"PUBLISHED_DESC","maxItems":20}`. Location IDs come from the Blocket Torget search filters and can identify counties or more specific areas. Copy the location parameter from a search URL to use the same area in an API request. This filter runs on the source before pagination, so other regions do not consume your result limit.

The published-today option uses the website’s own date boundary. It does not mean the preceding 24 hours, and it does not remember a previous run or identify only unseen ads between runs. Keep the `id` and `postedAt` columns in your downstream system if you want to compare scheduled runs. A narrow region combined with a date filter may legitimately have no matching ads; widen the region or disable the date filter in that case. Both options work with the existing category, price and seller filters, and neither adds detail-page requests.

### Output

Each ad becomes one dataset item. Here is a real example from a run with `includeDetails` enabled:

```json
{
  "id": "26702022",
  "sourceUrl": "https://www.blocket.se/recommerce/forsale/item/26702022",
  "title": "CUBE STEREO AMS Hybrid 177 C:62 / Medium, Large / KAMPANJ / EL-Cykel",
  "price": 59900,
  "currency": "SEK",
  "location": "Upplands Väsby",
  "sellerType": "business",
  "organisationName": "Cykelhuset",
  "images": [
    "https://images.blocketcdn.se/dynamic/default/item/26702022/d1338ec2-0a9f-42e7-8bd3-1fc5563e47df"
  ],
  "latitude": 59.5188,
  "longitude": 17.9114,
  "postedAt": "2026-10-01T09:45:07.000Z",
  "tradeType": "Säljes",
  "description": "Frame\nframe\nC:62® Monocoque Advanced Twin Mold Technology, Effiecient Trail Control, FSP 4-Link, Agile Trail\n\nSuspension\nSuspension fork\nFox 38 Float Performanc",
  "category": "Sport och friluftsliv > Cykling > Cyklar",
  "condition": "New"
}
```

The dataset has an overview table view in the Output tab, and you can export it in any format that Apify supports. Items are written as they are scraped, so you can read partial results while a run is still going.

### How much does it cost?

The Actor is charged per result: you pay for each ad saved to the dataset, and nothing for ads that are skipped as duplicates. See the Pricing tab of the Actor for the current rate. Because `maxItems` is enforced exactly, you can cap the cost of any run by setting it to the number of ads you need.

### Use with AI agents (MCP)

You can call this Actor from any MCP-compatible AI client through the Apify MCP server. Add it with this configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=axiomworks/blocket-ads-scraper"
    }
  }
}
```

Example prompts:

"Find the 30 newest bicycle ads on Blocket and list the cheapest five with their location."

"Search Blocket for 'soffa' and tell me the average asking price for private sellers."

"Get Blocket ads for the keyword 'iPhone 13' sorted by lowest price and show whether each seller is private or a business."

The agent sees the input schema, so it can set `queries`, `sort`, `maxItems` and `includeDetails` on its own.

### Integrations and API

You can start the Actor from code, schedule it, or connect it to other tools with Apify integrations such as webhooks, Make, Zapier, Google Sheets and n8n.

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("axiomworks/blocket-ads-scraper").call(run_input={
    "queries": ["cykel"],
    "maxItems": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["price"], item["currency"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('axiomworks/blocket-ads-scraper').call({
    queries: ['cykel'],
    maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
process.stdout.write(`${items.length} ads\n`);
```

cURL:

```bash
curl -X POST "https://api.apify.com/v2/acts/axiomworks~blocket-ads-scraper/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["cykel"], "maxItems": 50}'
```

### FAQ

**How many ads can I get per keyword?**
Blocket exposes about 50 pages of roughly 50 ads for each search, so around 2,500 ads per keyword and category combination. Use several keywords or categories to go beyond that.

**Does it cover cars, boats, jobs or property?**
No. Those live on other Blocket verticals. This Actor covers the general marketplace (Torget), where people sell used and new goods.

**Why are description, category and condition empty?**
They come from the individual ad page. Turn on `includeDetails` to fill them. Condition can still be empty when the seller did not specify one.

**Why is the price null for some ads?**
Some ads are free, offered for exchange or marked as contact-the-seller, and carry no price on the site.

**How fast is it?**
Search pages are requested about once or twice a second. With details enabled, ad pages are requested about once per second to stay polite to the site, so 100 ads with details take a couple of minutes.

**What happens with a keyword that has no results?**
The run finishes without errors, saves nothing for that keyword and writes a warning to the log. Invalid or non-Blocket URLs in Start URLs are skipped with a warning.

**What if requests get blocked?**
Requests that return a block or rate-limit response are retried with increasing delays. If direct requests keep failing, the Actor switches to Apify Proxy automatically. You can also enable Apify Proxy yourself in the input.

**Does it work with Swedish keywords?**
Yes. Search terms are sent as typed, so use Swedish words such as `cykel`, `soffa` or `begagnad`.

### Is it legal to scrape Blocket?

The Actor collects only information that any visitor can see without logging in, and it does not access accounts, private messages or personal contact details. Whether a particular use of public data is lawful depends on your country, your purpose and how you handle the data afterwards. Ads can contain personal data such as a location or photos of people, so if you store or share results you should follow data protection rules such as the GDPR, respect the site's terms, keep request volumes modest and avoid republishing content in ways that infringe copyright. If in doubt, ask a lawyer about your specific case. This section is general information and not legal advice.

### Feedback

If something is missing, a field looks wrong, or Blocket changes its pages and the Actor stops working, please open an issue from the Actor's Issues tab in Apify Console. Include the input you used and the run ID so the problem can be reproduced quickly.

# Actor input Schema

## `queries` (type: `array`):

Keywords to search, e.g. cykel or soffa. Supply queries, startUrls or a category. With default options, returns search-list fields without detail text. maxItems is shared across all searches; a missing or blocked target returns no ads.

## `startUrls` (type: `array`):

Blocket Torget search URLs as strings or URL objects. Alternative to queries; q, category, sort, price_from, price_to, location and published are read from each URL. URL filters override matching input options; absent filters use those options. maxItems is shared across targets. Item URLs are not detail targets.

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

Optional Blocket category ID to restrict the search, e.g. '0.91' (top level), '1.91.3108' (sub category) or '2.91.3108.362'. Leave empty to search all categories.

## `location` (type: `string`):

Restrict Torget searches to a Blocket location ID, e.g. 0.300001 for Stockholm county. Default empty searches all Sweden. A start URL location overrides this value; clear it if no ads match.

## `publishedToday` (type: `boolean`):

Return only ads Blocket marks as published today. Default false includes all dates. Uses the site’s published=1 filter, not a rolling 24-hour window. A start URL published parameter overrides this option.

## `sort` (type: `string`):

Result order: RELEVANCE (default), PRICE_ASC, PRICE_DESC or PUBLISHED_DESC (newest first).

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

Only ads priced at or above this amount in SEK, e.g. 500. Leave empty for no lower limit. Used for queries and URLs without price_from; should not exceed maxPrice.

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

Only ads priced at or below this amount in SEK, e.g. 2000. Leave empty for no upper limit. Used for queries and URLs without price_to; should not be below minPrice.

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

Seller filter: any (default), private or business, e.g. private. Applied after fetching; restrictive filters may return fewer than maxItems. Widen to any if no ads match.

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

Total ads to save across all keywords and URLs, 1-5000, default 50. Duplicate ads count once. Stops at this shared limit; Blocket shows about 50 pages per search.

## `includeDetails` (type: `boolean`):

Set true to fetch each saved ad page for description, fullDescription, category and condition; unavailable details stay null. False (default), e.g. false, returns search fields only. Adds a paced request per ad and increases runtime.

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

Apify Proxy settings. No proxy is used by default; if direct requests get blocked the Actor automatically retries through Apify datacenter proxy.

## Actor input object example

```json
{
  "queries": [
    "cykel"
  ],
  "startUrls": [],
  "category": "",
  "location": "",
  "publishedToday": false,
  "sort": "RELEVANCE",
  "sellerType": "any",
  "maxItems": 20,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "queries": [
        "cykel"
    ],
    "maxItems": 20,
    "includeDetails": false,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/blocket-ads-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 = {
    "queries": ["cykel"],
    "maxItems": 20,
    "includeDetails": False,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/blocket-ads-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 '{
  "queries": [
    "cykel"
  ],
  "maxItems": 20,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call axiomworks/blocket-ads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/blocket-ads-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/ChRFoC56qdVxJIBL1/builds/5aey4RKIKt4iolZX0/openapi.json
