DEV Community

Cover image for How to Scrape Allegro Poland and Czech Listings with Python
ReventaData
ReventaData

Posted on Originally published at apify.com

How to Scrape Allegro Poland and Czech Listings with Python

By the end of this tutorial, you will have a working Python script that extracts marketplace listings across Allegro Poland (allegro.pl) and Allegro Czech Republic (allegro.cz) into clean JSON records. You will extract product titles, prices, seller ratings, delivery options, and technical specifications directly from search results without maintaining browser instances or reverse-engineering anti-bot systems.

Allegro operates regional marketplaces across Central Europe. Automating data extraction allows developers to monitor price trends and audit merchant ratings.

In this guide, we use Python and two dedicated Apify Actors: Allegro.pl Scraper (reventadata/allegro-pl-scraper) and Allegro.cz Scraper (reventadata/allegro-cz-scraper). Both scrapers route requests through Bright Data Web Unlocker, managing sessions and concurrency automatically.

⏱️ Time estimate: one sitting: install one package, set one token, and run short Python blocks.


Prerequisites

To follow this tutorial, you will need:

  1. Python 3.11 or newer installed locally (apify-client 3.x requires it).
  2. The official Apify API client library for Python (pip install -U "apify-client~=3.0").
  3. An Apify account with an API token. You can sign up with email or GitHub.

Copy your personal API token from the API & Integrations page in Apify Console. Set your token as an environment variable in your terminal:

export APIFY_API_TOKEN="your_apify_token_here"
Enter fullscreen mode Exit fullscreen mode

Next, install the pinned client package:

pip install -U "apify-client~=3.0"
Enter fullscreen mode Exit fullscreen mode

What you'll achieve

By completing this guide, you will collect structured listing records from both Allegro Poland and Allegro Czech Republic. The returned dataset provides essential e-commerce fields:

  • Core listing data: offer identifiers, product titles, canonical URLs, and catalog product links.
  • Pricing and currencies: product prices in local currencies (PLN on allegro.pl and CZK on allegro.cz), and, on allegro.pl, cheapest delivery prices and total prices with delivery.
  • Merchant information: seller login names, numeric seller IDs, shop profile URLs, Super Seller badges, and positive feedback percentages.
  • Item attributes: product review averages, review counts, recent purchase volume labels, delivery badges, and hardware parameter dictionaries.

Note on Data Boundaries: These scrapers read public search result cards. They do not read private seller account data or pages behind a login.


Step 1: Access the Allegro Scrapers

To begin, visit the official Store pages for the two tools:

Both scrapers operate on public marketplace search results. The Poland scraper reads https://allegro.pl/listing?string=... while the Czech scraper reads https://allegro.cz/vyhledavani?string=.... In this guide, we drive both Actors programmatically using Python and the official apify-client SDK.


Step 2: Configure search parameters

The scrapers require at least one search query in the searchQueries array. For each term provided, the scraper queries the marketplace, walks the paginated search result pages, and collects product offers.

To keep data pipelines manageable, specify maxItems to cap the total number of items collected across all search terms. The input form prefills maxItems: 20 for quick exploratory runs, while defaulting to 100 for standard sweeps.

Here is how we set up the Python script and define a reusable execution helper:

import os
from apify_client import ApifyClient

# 1. Initialize ApifyClient with token from environment
client = ApifyClient(os.environ["APIFY_API_TOKEN"])

# 2. Helper to run an Allegro Actor, wait for completion, and return dataset items
def run_allegro_scraper(actor_id: str, run_input: dict) -> list[dict]:
    run = client.actor(actor_id).call(run_input=run_input)
    if run is None or run.status != "SUCCEEDED":
        status = run.status if run else "unknown"
        raise SystemExit(f"{actor_id} did not succeed (status: {status}).")
    return client.dataset(run.default_dataset_id).list_items().items
Enter fullscreen mode Exit fullscreen mode

💡 Tip: The helper function calls client.actor(actor_id).call(run_input=run_input), which triggers the Actor run in Apify's cloud infrastructure and waits for execution to settle before retrieving dataset items.


Step 3: Configure optional filters

Both scrapers provide native server-side parameters alongside row-level filters. Server-side parameters are sent directly in Allegro's search query URL, ensuring the site filters offers before returning results.

Parameter Type Default Description
searchQueries array Required List of search keywords. One search per term.
maxItems integer 100 Maximum products saved across all queries.
minPrice & maxPrice integer None Price boundaries (PLN on allegro.pl, CZK on allegro.cz). 0 is a valid minimum.
condition string "any" Offer condition filter: "any", "new", or "used".
freeDelivery boolean false Filters for listings offering free delivery.
smartOnly boolean false Filters for Allegro Smart! delivery listings (allegro.pl only).
superSellerOnly boolean false Filters for sellers with the Super Seller badge.
sortBy string "relevance" Sort order: "relevance", "price-asc", or "price-desc".
includeKeywords array [] Title and seller login must contain every word (accent-insensitive).
excludeKeywords array [] Drops offers whose title or seller login contains any word.
includeSponsored boolean true Includes paid sponsored listing placements.

When you request a server-side filter, the scraper verifies that Allegro echoed the filter parameter in the result page URL. If Allegro ignores a filter parameter, the scraper halts and raises a validation error instead of exporting unfiltered data.


Step 4: Run the extraction

With your configuration defined, run the script to trigger both scrapers sequentially:

# 3. Extract Poland listings from allegro.pl (PLN)
pl_results = run_allegro_scraper(
    "reventadata/allegro-pl-scraper",
    {
        "searchQueries": ["iphone"],
        "maxItems": 20,
        "condition": "used",
        "excludeKeywords": ["etui", "szkło", "case"],
    },
)

# 4. Extract Czech Republic listings from allegro.cz (CZK)
cz_results = run_allegro_scraper(
    "reventadata/allegro-cz-scraper",
    {
        "searchQueries": ["iphone"],
        "maxItems": 20,
        "condition": "new",
        "excludeKeywords": ["kryt", "sklo", "pouzdro"],
    },
)

print(f"Retrieved {len(pl_results)} Poland offers and {len(cz_results)} Czech offers.\n")

print("--- Poland Sample Offers (allegro.pl) ---")
for item in pl_results[:3]:
    print(f"[{item.get('id')}] {item.get('title')}")
    print(f"  Price: {item.get('price')} {item.get('currency')} | With delivery: {item.get('priceWithDelivery')} {item.get('currency')}")
    print(f"  Seller: {item.get('sellerLogin')} (Super Seller: {item.get('sellerSuperSeller')})")
    print(f"  URL: {item.get('url')}")

print("\n--- Czech Sample Offers (allegro.cz) ---")
for item in cz_results[:3]:
    print(f"[{item.get('id')}] {item.get('title')}")
    print(f"  Price: {item.get('price')} {item.get('currency')}")
    print(f"  Seller: {item.get('sellerLogin')} (Super Seller: {item.get('sellerSuperSeller')})")
    print(f"  URL: {item.get('url')}")
Enter fullscreen mode Exit fullscreen mode

Behind the scenes:

  • Both allegro.pl and allegro.cz deploy DataDome bot mitigations. The Actors route every listing request through Bright Data Web Unlocker, executing two raced requests per page across 3 concurrent pages in flight.
  • Scrapers deduplicate offers by offer ID across pages. An offer ID is marked as seen only after it passes all row filters and is successfully stored.
  • Allegro enforces a ceiling of 100 pages per search query (around 6,000 products for broad terms). If you request page 101 or navigate beyond the last available page, Allegro silently serves page 1 again; the scrapers detect this clamp and terminate the sweep immediately.
  • If a run reaches the platform charge limit, the scraper logs a warning and exits cleanly without throwing errors.

Step 5: View and download results

Once the runs complete, you can inspect individual records in Python or export the entire dataset through Apify Console in JSON, CSV, Excel, XML, or JSONL formats.

Here is a sample offer from Allegro Poland, from a capture dated 2026-10-22 (scraped timestamp omitted):

{
  "id": "17293334069",
  "title": "Smartfon Apple iPhone 16e 8 GB / 128 GB 5G biały",
  "url": "https://allegro.pl/oferta/17293334069",
  "productUrl": "https://allegro.pl/produkt/smartfon-apple-iphone-16e-8-gb-128-gb-5g-bialy-1d4f849c-f728-41bb-9f41-173e7ec2307a?offerId=17293334069",
  "price": 2879.04,
  "currency": "PLN",
  "priceWithDelivery": 2879.04,
  "deliveryLowestPrice": 0.0,
  "freeDelivery": true,
  "pricePerUnit": null,
  "imageUrl": "https://a.allegroimg.com/s180/11db45/33eb21a14e3494c194de302e493b/Smartfon-APPLE-iPhone-16e-5G-128GB-6-1-Bialy",
  "sellerLogin": "avans__pl",
  "sellerId": "42388365",
  "sellerUrl": "https://allegro.pl/uzytkownik/avans__pl",
  "sellerSuperSeller": true,
  "sellerIsCompany": true,
  "sellerPositiveFeedbackPercent": 98.3,
  "ratingAverage": 4.9,
  "ratingCount": 133,
  "popularityLabel": "30 osób kupiło ostatnio",
  "deliveryLabel": "Smart!",
  "bestPriceGuarantee": true,
  "parameters": {
    "Kolor": [
      "biały"
    ],
    "Przekątna ekranu": [
      "6.1\""
    ],
    "Wbudowana pamięć": [
      "128 GB"
    ],
    "Pamięć RAM": [
      "8 GB"
    ]
  },
  "productId": "1d4f849c-f728-41bb-9f41-173e7ec2307a",
  "productOffersCount": 67,
  "listingType": "regular",
  "matchedKeyword": "iphone",
  "page": 2
}
Enter fullscreen mode Exit fullscreen mode

Here is a sample offer from Allegro Czech Republic, from a capture dated 2026-10-21 (scraped timestamp omitted):

{
  "id": "18231547644",
  "title": "Smartphone Apple iPhone 17 Pro 12 GB / 256 GB 5G stříbrný",
  "url": "https://allegro.cz/nabidka/18231547644",
  "price": 28487.0,
  "currency": "CZK",
  "pricePerUnit": null,
  "imageUrl": "https://a.allegroimg.com/s180/11294d/bdf8e79e430ca43ae2e3f0b123a4/Smartphone-Apple-iPhone-17-Pro-256-GB-stribrny",
  "sellerLogin": "smartSPOT",
  "sellerId": "102969755",
  "sellerUrl": "https://allegro.cz/uzivatel/smartSPOT",
  "sellerSuperSeller": true,
  "sellerPositiveFeedbackPercent": 97.7,
  "ratingAverage": 4.96,
  "ratingCount": 238,
  "popularityLabel": "294 lidí nedávno koupilo",
  "deliveryLabel": null,
  "parameters": {
    "Barva": [
      "stříbrná"
    ],
    "Úhlopříčka displeje": [
      "6.3\""
    ],
    "Interní paměť": [
      "256 GB"
    ],
    "Paměť RAM": [
      "12 GB"
    ]
  },
  "productId": "c4920379-0f9c-4cfb-b58b-172354f83bce",
  "productOffersCount": 25,
  "listingType": "regular",
  "matchedKeyword": "iphone",
  "page": 2
}
Enter fullscreen mode Exit fullscreen mode

Understanding your results

Each record stored in the dataset adheres to a structured schema:

  • id: Distinct offer identifier string assigned by Allegro.
  • title: Product title displayed on the result card.
  • url: Direct canonical offer link without tracking parameters.
  • productUrl: Link to the catalog product overview page when available.
  • price and currency: Selling price as a float, with currency code (PLN or CZK).
  • priceWithDelivery & deliveryLowestPrice: Delivery costs on allegro.pl.
  • freeDelivery: Boolean indicating whether free delivery applies.
  • sellerLogin, sellerId, & sellerUrl: Merchant identity, account ID, and store link.
  • sellerSuperSeller: True when the seller holds Super Seller status.
  • sellerPositiveFeedbackPercent: Proportion of positive buyer feedback ratings.
  • ratingAverage & ratingCount: Review score average and total review count.
  • popularityLabel: Marketplace text showing recent purchases.
  • deliveryLabel: Delivery badge text, such as "Smart!" on allegro.pl.
  • bestPriceGuarantee: Indicates whether the listing carries Allegro's lowest price guarantee (allegro.pl rows only).
  • parameters: Key-value dictionary of product specifications.
  • listingType: Classification of placement (regular, promoted, or sponsored).
  • matchedKeyword & page: Search query and page number.

Pro tips

  1. Ceiling awareness on broad queries: Allegro serves at most 100 pages per search term (about 6,000 products). When scraping large categories with tens of thousands of items, subdivide your sweep into narrower price brackets using minPrice and maxPrice.
  2. Clean up fuzzy search matches: Allegro's search engine uses fuzzy keyword matching, which occasionally returns unrelated products or accessories. Use excludeKeywords: ["etui", "szkło", "case", "kryt", "pouzdro"] to strip phone cases and screen protectors from device searches.
  3. Filter established merchants: If you want to eliminate newly created accounts or unverified sellers, set superSellerOnly: true to restrict results to merchants holding Allegro's Super Seller status.
  4. Enforce price boundaries: The scrapers pass price bands to Allegro's search URL and re-verify every returned row against minPrice and maxPrice, dropping ad rows that fall outside your target range.
  5. Start small during development: When integrating Allegro data into custom applications, begin testing with maxItems: 20 to validate schema mappings before launching comprehensive sweeps.

Troubleshooting

  • Run failed with 0 rows: If a search query or filter combination produces zero stored records, the Actor intentionally raises a runtime error rather than succeeding silently. Verify your spelling and ensure your price bands or keyword exclusion lists are not overly restrictive.
  • Filter rejected by marketplace: The scraper checks page URLs to ensure Allegro applied all requested server-side filters. If a filter is ignored, the scraper stops immediately with a validation error to prevent exporting unfiltered records.
  • Invalid input parameters: Fixed options such as condition and sortBy are strictly validated against schema enums; an invalid value is refused before the run starts.
  • Reading execution logs: The final lines of each run log print the count of pushed rows and a tally of rejected items. You can inspect logs via client.log(run.id).get().

Next steps

For current pricing and details, see the Store page.

You can automate recurring extractions by configuring Apify schedules, which trigger Actor runs on standard cron expressions (such as 0 8 * * *). Furthermore, you can attach webhooks to notify external web services when runs complete; webhook payloads deliver run metadata including defaultDatasetId for automated downstream data ingestion.

What categories or product deals are you planning to track across Allegro Poland and Czech Republic? Let us know in the comments below! 💬

About the author: reventadata builds scrapers for global marketplaces and classifieds.

Top comments (0)