# Hudební Bazar Scraper — hudebnibazar.cz musical gear (`richardsolar/hudebnibazar-scraper`) Actor

Scrape hudebnibazar.cz, the Czech marketplace for used musical instruments and gear. Search by keyword, category, region and advert type, with prices in CZK and EUR, seller profiles, every photo, and an incremental mode that returns only new adverts.

- **URL**: https://apify.com/richardsolar/hudebnibazar-scraper.md
- **Developed by:** [Richard Solar](https://apify.com/richardsolar) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

Hudební Bazar Scraper extracts classified adverts from **hudebnibazar.cz**, the Czech marketplace for used musical instruments and gear — around 14,000 live adverts across guitars, drums, keyboards, studio equipment, lessons and rehearsal rooms.

Search the way the site itself does. Keyword, category, region, advert type and sort order all go to the server, so you fetch what you asked for rather than filtering a firehose afterwards.

No account, no cookies, no setup.

### Why this one

- **List-only mode loses almost nothing.** Results pages on this site already carry the title, price in CZK and EUR, town, seller nickname and **every photo** — not just a thumbnail. Turning listing details off uses about 30x fewer requests and still gives you a usable dataset.
- **Wanted adverts are labelled.** The site mixes "koupím" (wanted) adverts into the same results as "prodám" (for sale). `offerType` tells them apart, and you can ask for one or the other.
- **Prices in both currencies.** The site publishes its own EUR conversion beside the CZK price; both come back as numbers.
- **Monitoring built in.** A scheduled run returns only adverts posted since the last one.
- **The run tells you when it breaks.** Every field has an expected fill rate. If the site changes its markup, the run says which fields stopped filling instead of quietly returning empty columns.

### How much does it cost?

| Mode                   | Effective price  | What you get                                                                    |
| ---------------------- | ---------------- | ------------------------------------------------------------------------------- |
| `scrapeDetails: false` | **$1 per 1,000** | Title, price, town, seller nickname, every photo, results-page date             |
| `scrapeDetails: true`  | **$2 per 1,000** | Everything — full description, exact posting time, view count, category, seller |

Starting a run costs $0.00005.

`maxItems` is enforced as adverts are collected, not trimmed afterwards, so the Actor never returns — or bills — more than you asked for.

### Input examples

**Everything in one category**

```json
{
  "category": "elektricke-kytary/110100",
  "sortBy": "cheapest",
  "maxItems": 200,
  "scrapeDetails": true
}
```

**A keyword across the whole site, Prague and Central Bohemia only**

```json
{
  "keywords": ["stratocaster"],
  "regions": ["1", "2"],
  "sortBy": "newest",
  "maxItems": 100,
  "scrapeDetails": false
}
```

**What people are looking to buy**

```json
{
  "category": "bici-soupravy/190100",
  "offerType": "buy",
  "maxItems": 100,
  "scrapeDetails": true
}
```

### Monitoring: only what is new

Set `monitorMode: true` and the Actor remembers which adverts it has already returned. The next run skips them, so a schedule costs only what appeared since last time — and an advert you have already paid for is never charged twice.

```json
{
  "category": "kytarove-efekty/110500",
  "priceMax": 5000,
  "sortBy": "newest",
  "maxItems": 300,
  "scrapeDetails": true,
  "monitorMode": true
}
```

Save that as a task and schedule it hourly. The first run returns everything matching; every run after it returns only new adverts.

Known adverts are dropped while reading the results page, so they cost neither a request nor a charge. The run status says how many were skipped, which is how you tell "nothing new" apart from "something broke".

Ids are kept for 90 days by default (`monitorRetentionDays`). Two schedules watching different searches need two different `monitorStoreName` values, or each will hide the other's adverts.

### Output example

Each advert comes back as 28 separate fields:

```json
{
  "listingId": "44810",
  "url": "https://hudebnibazar.cz/stratocaster-texas-series-guitarfantasy/ID44810/",
  "categoryId": "110100",
  "categorySlug": "elektricke-kytary",
  "categoryLabel": "Elektrické kytary",
  "categoryPath": "Kytary › Elektrické kytary",
  "title": "Stratocaster Texas series Guitarfantasy",
  "descriptionShort": "Elektrická kytara kopie Stratocaster Texas series…",
  "description": "Elektrická kytara kopie Stratocaster Texas series Guitarfantasy, Made in Italy, r.v.1990…",
  "offerType": "sell",
  "price": 14990,
  "priceEur": 615.4,
  "priceText": "14 990 Kč",
  "city": "Ostrava",
  "sellerNick": "Jack.Country",
  "sellerName": "Jack Country",
  "sellerUserId": "17694",
  "sellerUrl": "https://hudebnibazar.cz/uzivatel/detail/?ID=17694",
  "sellerCity": "Ostrava",
  "sellerRegisteredAt": "2016-10",
  "viewCount": 20739,
  "publishedAt": "2026-09-13T06:11:00.000Z",
  "publishedText": "pondělí 7. září",
  "thumbnailUrl": "https://img.hudebnibazar.cz/img_cache/158x158-3/img_inz/2016-11/07ebbf.avif",
  "mainImage": "https://img.hudebnibazar.cz/img_cache/1920x1920-0/img_inz/2016-11/07ebbf.avif",
  "images": [
    "https://img.hudebnibazar.cz/img_cache/1920x1920-0/img_inz/2016-11/07ebbf.avif"
  ],
  "sourceUrl": "https://hudebnibazar.cz/stratocaster-texas-series-guitarfantasy/ID44810/",
  "scrapedAt": "2026-09-13T08:02:11.318Z"
}
```

### What can you use it for?

- **Price research** — what a used instrument actually sells for in the Czech market, in CZK and EUR.
- **Sourcing and resale** — watch a category for underpriced gear and get alerted the same hour.
- **Demand signals** — wanted adverts show what buyers are hunting for and cannot find.
- **Market analysis** — 14,000 adverts across 89 categories, with view counts as a proxy for interest.

### Tips

#### Scope to a category

89 categories, listed as full paths like `Kytary › Elektrické kytary`. A category is the cheapest way to cut irrelevant results, and the site applies it server-side.

You can pass the `slug/id` pair the dropdown lists, or just the slug, or just the numeric id — whichever half of a category URL you happen to have.

#### Regions

Fourteen Czech regions plus Slovakia, which the site treats as a region rather than a country. Pass several to widen the search.

#### The price filter runs here, not on the site

hudebnibazar has no price filter in its own UI, so `priceMin` and `priceMax` are applied to the adverts this Actor collects. Pages are still fetched, but adverts outside the range are dropped before any detail request and are never charged. Adverts with no stated price — "cena dohodou" — are kept, because dropping them would hide every negotiable advert from a price-bounded search.

#### Sort order

`newest`, `cheapest` and `mostExpensive`, all applied by the site.

### FAQ

#### Can I get the seller's phone number?

No. hudebnibazar shows contact details only to signed-in users, and this Actor does not sign in. You get the public profile URL, display name, nickname, town and registration month.

#### Why is `price` sometimes null?

Because the advert says "cena dohodou" — price by agreement — rather than a number. `priceText` keeps the label so you can tell that apart from a missing value.

#### Is `publishedAt` accurate?

Yes, to the minute, and it is converted from Prague local time to UTC. It only appears in detail mode; results pages print a weekday instead, which is kept verbatim in `publishedText`.

#### Does it respect robots.txt?

Yes. The site's robots.txt explicitly allows category listings and advert detail pages, and blocks login, private messages and internal endpoints. This Actor only reads the allowed pages, and runs at low concurrency.

#### Is scraping this legal?

Scraping publicly available data is generally legal, but this Actor collects personal data such as seller names and towns. You are responsible for having a lawful basis to process it under GDPR. If you are unsure, take legal advice — and consider turning listing details off if you only need prices.

#### Something looks wrong

Report it on the **Issues** tab. This Actor checks the live site daily, so markup changes are usually caught before users notice.

# Actor input Schema

## `keywords` (type: `array`):

Search terms. Each one runs as its own search and they share the listing cap. Leave empty to browse a category, or everything.

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

One category, listed as its full path. A value is `slug/id` as the site numbers them: `kytary/110000` for Guitars, `elektricke-kytary/110100` for Electric guitars. Leave on "All categories" to search everything. Scoping to a category is the cheapest way to cut irrelevant results, and the site applies it server-side.

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

Czech regions, plus Slovakia, which the site treats as a region of its own. Empty means every region.

## `offerType` (type: `string`):

Whether the advert offers something or asks for it. The site mixes both in its results unless you choose.

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

Applied by the site, not afterwards.

## `priceMin` (type: `integer`):

Applied to the listings this run collects — hudebnibazar has no price filter of its own, so there is nothing to delegate to. Pages are still fetched, but rows outside the range are dropped before any detail request and are never charged. Adverts with no stated price are kept.

## `priceMax` (type: `integer`):

See the note on minimum price. Adverts with no stated price are kept. A maximum below the minimum fails the run rather than returning an almost empty dataset.

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

Hard cap on listings returned, shared across every keyword. Enforced as listings are collected, so you are never billed for overshoot.

## `maxPagesPerSearch` (type: `integer`):

0 means no limit. Each page holds 30 listings.

## `scrapeDetails` (type: `boolean`):

Adds the full description, exact posting time, view count, category and seller profile. Results pages already carry the title, price, town, seller nickname and every photo, so turning this off costs less here than on most classifieds sites — and uses about 30x fewer requests.

## `monitorMode` (type: `boolean`):

Skip listings an earlier run already returned. Skipped listings are not opened and not charged. Leave off for one-off runs.

## `monitorStoreName` (type: `string`):

Named key-value store holding the ids already returned. Leave empty to use one named after the Actor. Give two schedules two different names when they watch different searches, or each will hide the other’s listings.

## `monitorRetentionDays` (type: `integer`):

How long an id stays remembered. Older ids are dropped, so the store does not grow forever.

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

Listing or results-page URLs to scrape directly. Passing these replaces the generated search unless you also give a keyword or category.

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

Apify Proxy. The datacenter pool is fine here; this site does not block it.

## `minCleanFieldRatio` (type: `number`):

Advanced. Every field has an expected fill rate; the run warns and names any field that drops below its own. Leave at 1 and the run only warns. Lower it to fail the run when more than this fraction of fields are affected.

## Actor input object example

```json
{
  "keywords": [
    "stratocaster"
  ],
  "category": "",
  "regions": [],
  "offerType": "all",
  "sortBy": "newest",
  "maxItems": 20,
  "maxPagesPerSearch": 0,
  "scrapeDetails": true,
  "monitorMode": false,
  "monitorStoreName": "",
  "monitorRetentionDays": 90,
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "minCleanFieldRatio": 1
}
```

# 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 = {
    "keywords": [
        "stratocaster"
    ],
    "offerType": "all",
    "sortBy": "newest",
    "maxItems": 20,
    "scrapeDetails": true,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("richardsolar/hudebnibazar-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 = {
    "keywords": ["stratocaster"],
    "offerType": "all",
    "sortBy": "newest",
    "maxItems": 20,
    "scrapeDetails": True,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("richardsolar/hudebnibazar-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 '{
  "keywords": [
    "stratocaster"
  ],
  "offerType": "all",
  "sortBy": "newest",
  "maxItems": 20,
  "scrapeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call richardsolar/hudebnibazar-scraper --silent --output-dataset

```

## MCP server setup

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