# BazosScraper (`lupine_historian/bazosscraper`) Actor

Scrapes ads from Bazos.cz and Bazos.sk with support for multiple search queries, price and location filters, automatic pagination and detailed ad data extraction. Built on Apify + Crawlee with residential proxy support and configurable concurrency.

- **URL**: https://apify.com/lupine\_historian/bazosscraper.md
- **Developed by:** [Identic API](https://apify.com/lupine_historian) (community)
- **Categories:** E-commerce, Integrations, Real estate
- **Stats:** 15 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## Bazos Scraper

A web scraper for extracting advertisements from [Bazos.cz](https://www.bazos.cz) and [Bazos.sk](https://www.bazos.sk) - the largest classified ads portals in Czech Republic and Slovakia.

### Description

This scraper allows you to search for advertisements using multiple keywords simultaneously, filter by price range and location, and extract comprehensive data about each listing. It's built with [Apify](https://apify.com) and [Crawlee](https://crawlee.dev) frameworks.

#### Features

- ✅ Support for both **Bazos.cz** (Czech Republic) and **Bazos.sk** (Slovakia)
- ✅ **Multiple keyword search** - search with multiple queries and get merged results
- ✅ **Price filtering** - filter by minimum and maximum price
- ✅ **Location filtering** - search by postal code and distance radius
- ✅ **Automatic pagination** - automatically follows all pages of search results
- ✅ **Comprehensive data extraction** - extracts title, price, location, views, description, images, user name, and more
- ✅ **Residential proxy support** - uses Apify's residential proxies for reliable scraping
- ✅ **Optimized performance** - parallel processing with configurable concurrency for faster scraping
- ✅ **Bilingual support** - automatically handles Czech and Slovak language variations

#### Input Configuration

The scraper accepts input via Apify Actor input or uses default configuration. You can provide input as JSON:

```json
{
    "countryCode": "cz",
    "searchQueries": ["iphone 13", "iphone 13 pro"],
    "minPrice": 200,
    "maxPrice": 500,
    "postalCode": 81101,
    "distance": 50,
    "maxRequests": 100
}
```

##### Input Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `countryCode` | `"cz" \| "sk"` | No | Country code - `"cz"` for Czech Republic, `"sk"` for Slovakia. Default: `"cz"` |
| `searchQueries` | `string[]` | **Yes** | Array of search keywords. Maximum 15 queries. |
| `postalCode` | `number \| null` | No | Postal code for location filtering (10000-99999). |
| `distance` | `number \| null` | No | Search radius in kilometers. Minimum: 1. |
| `minPrice` | `number \| null` | No | Minimum price filter. Must be >= 0. |
| `maxPrice` | `number \| null` | No | Maximum price filter. Must be >= 0. |
| `maxRequests` | `number` | **Yes** | Maximum number of HTTP requests (for Apify billing). The crawler will automatically stop when it reaches this limit. Note: Some requests are used for search result pages, so the actual number of ads extracted will be slightly less than maxRequests. Minimum: 1. Default: 100. |

**Important:** `maxRequests` limits the total number of HTTP requests made (this is what Apify bills you for). The actual number of ads extracted will be less because:

- Each search query = 1 request (initial search page)
- Search result pages = 1 request each
- Each ad detail = 1 request

**Example:** If you set `maxRequests: 20` with 3 search queries:

- 3 requests for initial search pages
- \~2 requests for result pages
- \~15 requests for ad details
- **Result:** ~15 ads extracted, 20 requests billed

##### Example Inputs

**Basic search:**

```json
{
    "countryCode": "sk",
    "searchQueries": ["notebook"],
    "maxRequests": 50
}
```

**Advanced search with filters:**

```json
{
    "countryCode": "cz",
    "searchQueries": ["iphone 13", "iphone 13 pro", "iphone 13 pro max"],
    "minPrice": 10000,
    "maxPrice": 30000,
    "postalCode": 10000,
    "distance": 50,
    "maxRequests": 200
}
```

**To get approximately 15 ads:**

```json
{
    "countryCode": "cz",
    "searchQueries": ["iphone 13", "iphone 13 pro"],
    "maxRequests": 20
}
```

Note: With 2 search queries, you'll get ~15 ads (20 requests - 2 for search pages - 2 for result pages = ~16 requests for ads)

### Output

The scraper outputs data to Apify Dataset. Each record contains the following fields:

#### Output Schema

```typescript
{
    id: number;              // Unique advertisement ID
    title: string;           // Advertisement title
    date: string;           // Publication date in ISO format (YYYY-MM-DD)
    priceRaw: string;       // Price as displayed on the website (e.g., "450 €", "Dohodou")
    locationPsc: string;   // Postal code of the location
    locationName: string;   // City/town name
    views: number;         // Number of views
    url: string;            // Full URL to the advertisement
    content: string;        // Full description text
    imageUrl: string;       // URL to the first/main image
    userName: string;       // Name of the user who posted the ad
}
```

#### Example Output

```json
{
    "id": 123456,
    "title": "iPhone 13 Pro 256GB",
    "date": "2024-01-15",
    "priceRaw": "450 €",
    "locationPsc": "81101",
    "locationName": "Bratislava",
    "views": 123,
    "url": "https://www.bazos.sk/inzerat/123456/iphone-13-pro-256gb/",
    "content": "Predám iPhone 13 Pro 256GB v perfektnom stave...",
    "imageUrl": "https://www.bazos.sk/img/123456.jpg",
    "userName": "Ján"
}
```

### License

ISC

# Actor input Schema

## `countryCode` (type: `string`):

Select country for searching

## `searchQueries` (type: `array`):

Search queries - you can enter multiple keywords to search

## `postalCode` (type: `integer`):

Postal code of the area where you want to search

## `distance` (type: `integer`):

Distance in kilometers from the specified location

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

Minimum price

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

Maximum price

## `maxRequests` (type: `integer`):

Maximum number of HTTP requests to make (for Apify billing). The crawler will automatically stop when it reaches this limit. Note: Some requests are used for search result pages, so the actual number of ads extracted will be slightly less than maxRequests.

## Actor input object example

```json
{
  "countryCode": "cz",
  "searchQueries": [
    "iphone 13",
    "iphone 13 pro",
    "iphone 13 pro max"
  ],
  "distance": 25,
  "maxRequests": 15
}
```

# 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 = {
    "searchQueries": [
        "iphone 13",
        "iphone 13 pro",
        "iphone 13 pro max"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lupine_historian/bazosscraper").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 = { "searchQueries": [
        "iphone 13",
        "iphone 13 pro",
        "iphone 13 pro max",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lupine_historian/bazosscraper").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 '{
  "searchQueries": [
    "iphone 13",
    "iphone 13 pro",
    "iphone 13 pro max"
  ]
}' |
apify call lupine_historian/bazosscraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lupine_historian/bazosscraper"
        }
    }
}

```

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/qb2b4bnIfqvgfNWfz/builds/jheIxoeOziAKFSt8x/openapi.json
