<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Norbert Sobala</title>
    <description>The latest articles on DEV Community by Norbert Sobala (@norbertso).</description>
    <link>https://dev.to/norbertso</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4194910%2F2bd76f8d-af63-4c5e-a4a7-009c9f9d1375.jpeg</url>
      <title>DEV Community: Norbert Sobala</title>
      <link>https://dev.to/norbertso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/norbertso"/>
    <language>en</language>
    <item>
      <title>How to compare all sellers of one Allegro product by price and condition in Python</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Mon, 02 Nov 2026 08:36:02 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-compare-all-sellers-of-one-allegro-product-by-price-and-condition-in-python-5f2m</link>
      <guid>https://dev.to/norbertso/how-to-compare-all-sellers-of-one-allegro-product-by-price-and-condition-in-python-5f2m</guid>
      <description>&lt;p&gt;Allegro groups offers for the same item under one catalogue product page. That page is where sellers fight on price, and it is also where a quick glance misleads you: new units, ex-display stock, used phones and damaged ones all sit in one list. If you do repricing or keep an eye on distributors, you want that list as a table you can filter.&lt;/p&gt;

&lt;p&gt;This guide uses the &lt;a href="https://apify.com/liveclaude/allegro-price-comparison" rel="noopener noreferrer"&gt;Allegro Price Comparison&lt;/a&gt; actor on Apify. You paste a product or offer link and it returns every seller offer for that product. I ran it this morning on one product, the black iPhone 15 256 GB, and every number below comes from that run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gxxerw1spxoykzrd42e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gxxerw1spxoykzrd42e.png" alt="Allegro Price Comparison dataset for iPhone 15 256 GB" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the run returned
&lt;/h2&gt;

&lt;p&gt;Input was a single product URL with &lt;code&gt;topNOffers&lt;/code&gt; set to 25. The log reported 57 offers on the product page, and the actor returned 22 offer rows in 33 seconds.&lt;/p&gt;

&lt;p&gt;A few things stood out once the data was in a table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prices ran from 1,359 PLN to 2,999.90 PLN, with a median of 2,119 PLN.&lt;/li&gt;
&lt;li&gt;Only one of the 22 offers was listed as new (&lt;code&gt;Stan: Nowy&lt;/code&gt;), at 2,999.90 PLN. Ten were used, eight were ex-display ("Powystawowy"), two were seller-refurbished and one was marked as damaged.&lt;/li&gt;
&lt;li&gt;The cheapest row (1,359 PLN) was the damaged unit. The cheapest used phone was 1,400 PLN.&lt;/li&gt;
&lt;li&gt;21 of 22 offers had Allegro Smart!, and only one carried the Lowest Price Guarantee badge.&lt;/li&gt;
&lt;li&gt;Two of the top three rows were promoted listings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the "lowest price" for this product, which the actor also reports as &lt;code&gt;lowestPriceForProduct: 1359&lt;/code&gt;, is a damaged phone. If you compare your own new stock against that number, your repricing rule will do something silly. Grouping by condition fixes it, and the Python section shows how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fields you get
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;outputFormat: "offers"&lt;/code&gt; you get one row per seller offer. The most useful columns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;th&gt;Example from the run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offerRank&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Position in the product's offer list&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Offer title as the seller wrote it&lt;/td&gt;
&lt;td&gt;Smartfon Apple iPhone 15 6 GB / 256 GB 5G czarny&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;price&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Item price&lt;/td&gt;
&lt;td&gt;2999.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;priceWithDelivery&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Price plus cheapest delivery&lt;/td&gt;
&lt;td&gt;3010.39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deliveryFrom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cheapest delivery cost&lt;/td&gt;
&lt;td&gt;10.49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deliveryTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delivery estimate shown on Allegro&lt;/td&gt;
&lt;td&gt;dostawa jutro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;smart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allegro Smart! eligible&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lowestPriceGuarantee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"Gwarancja najniższej ceny" badge&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;promoted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sponsored placement&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;superSeller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Super Seller badge&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerRating&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Positive feedback percentage&lt;/td&gt;
&lt;td&gt;95.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerIsCompany&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Business seller flag&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;parameters&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Offer parameters such as condition and warranty&lt;/td&gt;
&lt;td&gt;{"Stan": "Nowy", "Gwarancja": "12 miesięcy"}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;productRating&lt;/code&gt;, &lt;code&gt;productReviewsCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Catalogue product rating&lt;/td&gt;
&lt;td&gt;4.79, 106&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lowestPriceForProduct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lowest price on the product page&lt;/td&gt;
&lt;td&gt;1359&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;url&lt;/code&gt;, &lt;code&gt;offerId&lt;/code&gt;, &lt;code&gt;scrapedAt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Offer link, ID and timestamp&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are also seller identifier fields (&lt;code&gt;sellerLogin&lt;/code&gt;, &lt;code&gt;sellerId&lt;/code&gt;, &lt;code&gt;sellerUrl&lt;/code&gt;). In this run every seller was flagged as a company, but on a marketplace you can still hit private sellers, so the screenshots here leave those columns out and the Python example drops them before export.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;outputFormat: "products"&lt;/code&gt; you instead get one record per product with an &lt;code&gt;offers[]&lt;/code&gt; array plus &lt;code&gt;lowestPrice&lt;/code&gt;, &lt;code&gt;highestPrice&lt;/code&gt;, &lt;code&gt;avgPrice&lt;/code&gt; and &lt;code&gt;offerCount&lt;/code&gt;. That suits dashboards. For analysis I prefer the flat version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input options
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fta04wacto7tvyztn4ipj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fta04wacto7tvyztn4ipj.png" alt="Allegro Price Comparison input form" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;productUrls&lt;/strong&gt;: product links (&lt;code&gt;/produkt/...&lt;/code&gt;) or offer links (&lt;code&gt;/oferta/...&lt;/code&gt;), one per line. If you paste an offer link, the actor finds the catalogue product behind it. Allegro.pl, .cz and .sk all work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;topNOffers&lt;/strong&gt;: how many offers to return per product, 1 to 500, default 20.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sortBy&lt;/strong&gt;: &lt;code&gt;price-asc&lt;/code&gt;, &lt;code&gt;price-desc&lt;/code&gt; or &lt;code&gt;rating-desc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;smartFilter&lt;/strong&gt;: all offers, Smart! only, or no Smart!.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;includePromoted&lt;/strong&gt;: switch off to drop sponsored offers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;detectHiddenDiscounts&lt;/strong&gt;: for offers with the Lowest Price Guarantee badge, it reveals the price the seller actually set and the discount Allegro applies on top (&lt;code&gt;realSellerPrice&lt;/code&gt;, &lt;code&gt;hiddenDiscount&lt;/code&gt;). Charged per checked offer, so leave it off unless you need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onlyChanges&lt;/strong&gt; and &lt;strong&gt;monitorId&lt;/strong&gt;: monitoring mode. Each run returns only new offers and offers whose price moved since the last run, with &lt;code&gt;previousPrice&lt;/code&gt; and &lt;code&gt;priceChange&lt;/code&gt;. Unchanged offers are not charged.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/allegro-price-comparison" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click Try for free.&lt;/li&gt;
&lt;li&gt;In the Input tab paste your product links. The iPhone 15 link is prefilled if you just want to look.&lt;/li&gt;
&lt;li&gt;Set "Top N offers per product" and pick "One row per offer" as output format.&lt;/li&gt;
&lt;li&gt;Click Start. My single-product run took about half a minute.&lt;/li&gt;
&lt;li&gt;Open the Output tab and export to Excel, CSV or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Excel, add a filter on the parameters column and look at one condition at a time. That alone gives you a far more honest price spread than the product page does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python with pandas
&lt;/h2&gt;

&lt;p&gt;Install the client and pandas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas openpyxl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the actor and summarise by condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;productUrls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://allegro.pl/produkt/smartfon-apple-iphone-15-6-gb-256-gb-5g-czarny-b7d39356-8090-4bcf-9247-b872c5f6935a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;topNOffers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sortBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-asc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outputFormat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/allegro-price-comparison&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Condition lives inside the parameters dict ("Stan" on Allegro.pl)
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Organic offers only, cheapest first, with delivery included
&lt;/span&gt;&lt;span class="n"&gt;organic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;promoted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceWithDelivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;organic&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offerRank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceWithDelivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Drop seller identifiers before you share the file
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerLogin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iphone15_offers.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my run the summary came out like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;condition&lt;/th&gt;
&lt;th&gt;count&lt;/th&gt;
&lt;th&gt;min&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;max&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uszkodzony (damaged)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1359.00&lt;/td&gt;
&lt;td&gt;1359.00&lt;/td&gt;
&lt;td&gt;1359.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Używany (used)&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1400.00&lt;/td&gt;
&lt;td&gt;1949.00&lt;/td&gt;
&lt;td&gt;2219.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Powystawowy (ex-display)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1990.00&lt;/td&gt;
&lt;td&gt;2154.00&lt;/td&gt;
&lt;td&gt;2189.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Odnowiony przez sprzedawcę (refurbished)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2156.98&lt;/td&gt;
&lt;td&gt;2201.00&lt;/td&gt;
&lt;td&gt;2245.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nowy (new)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2999.90&lt;/td&gt;
&lt;td&gt;2999.90&lt;/td&gt;
&lt;td&gt;2999.90&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap between the median used phone and the one new offer was about 1,050 PLN. If you sell new units, the useful benchmark is the "Nowy" row, and with only one new offer in the top 25 you would raise &lt;code&gt;topNOffers&lt;/code&gt; to see more of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and integrations
&lt;/h2&gt;

&lt;p&gt;For competitor tracking, turn on &lt;code&gt;onlyChanges&lt;/code&gt;, give the watch list a &lt;code&gt;monitorId&lt;/code&gt; such as &lt;code&gt;competitors-iphone&lt;/code&gt;, and add a daily Schedule in Apify Console. Each run then returns only new offers and price changes. From there you can push results to Google Sheets, Slack, Make, Zapier or n8n, or pull them over the Apify API. The actor can also be called from AI agents through the Apify MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;The actor is pay per event. Current prices per 1,000 events:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free plan&lt;/th&gt;
&lt;th&gt;Business plan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Seller offer scraped&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product compared&lt;/td&gt;
&lt;td&gt;$8.00&lt;/td&gt;
&lt;td&gt;$6.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Starter and Scale plans fall in between. My run had 22 offer events, so at Free plan prices the offers cost about $0.044. Hidden discount detection is billed separately per checked offer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The actor reads publicly visible listing data. Keep request volumes reasonable, respect Allegro's terms, and treat any seller identifiers as potential personal data under GDPR: drop or pseudonymise them unless you have a clear reason to store them. Use the output for price analysis, not for contacting individual sellers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>webscraping</category>
      <category>pandas</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>How to pull open EU public tenders from TED into Python and pandas</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Fri, 30 Oct 2026 08:27:22 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-pull-open-eu-public-tenders-from-ted-into-python-and-pandas-3j98</link>
      <guid>https://dev.to/norbertso/how-to-pull-open-eu-public-tenders-from-ted-into-python-and-pandas-3j98</guid>
      <description>&lt;p&gt;Public tenders in Europe are published in one place: TED (Tenders Electronic Daily), the EU's official procurement journal. The data is open. The problem is volume and format. Notices arrive in 24 languages, values come in PLN, CZK or SEK, and the TED search UI is fine for browsing but slow if you want a daily shortlist in a spreadsheet.&lt;/p&gt;

&lt;p&gt;This guide shows how I pull open tenders from TED into a table with the &lt;a href="https://apify.com/flarewow/eu-tenders-ted-scraper" rel="noopener noreferrer"&gt;EU Tenders Scraper (TED)&lt;/a&gt; on Apify, first with no code, then with Python and pandas.&lt;/p&gt;

&lt;p&gt;For the examples I ran one real search this morning: keyword &lt;code&gt;cybersecurity&lt;/code&gt;, open tenders only, published in the last month, capped at 40 results. It returned 18 notices in 4.4 seconds. All numbers below come from that run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F313u6l6817i2vklsnvha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F313u6l6817i2vklsnvha.png" alt="TED cybersecurity tenders in a table" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;p&gt;Each row is one TED notice. The output has around 55 fields. These are the ones I use most:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;th&gt;Example from my run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noticeId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TED notice number&lt;/td&gt;
&lt;td&gt;&lt;code&gt;755875-2026&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Title in the original language&lt;/td&gt;
&lt;td&gt;Development, Implementation, Maintenance and Operation of financial IT Systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;buyerName&lt;/code&gt;, &lt;code&gt;buyerCountry&lt;/code&gt;, &lt;code&gt;buyerCity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Contracting authority&lt;/td&gt;
&lt;td&gt;European Commission, DG BUDG, BE, Brussels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;cpvMain&lt;/code&gt;, &lt;code&gt;cpvLabel&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Main CPV code and its label&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;72000000&lt;/code&gt;, IT services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;contractType&lt;/code&gt;, &lt;code&gt;procedureType&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Services / supplies / works, open / restricted etc.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;services&lt;/code&gt;, &lt;code&gt;open&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;estimatedValueEur&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Estimated value converted to EUR&lt;/td&gt;
&lt;td&gt;700000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;deadline&lt;/code&gt;, &lt;code&gt;daysToDeadline&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Submission deadline and days left&lt;/td&gt;
&lt;td&gt;2026-11-30, 32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lotsCount&lt;/code&gt;, &lt;code&gt;lots&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Number of lots with title and value per lot&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;suitableForSme&lt;/code&gt;, &lt;code&gt;euFunded&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Flags set by the buyer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;True&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;documentsUrl&lt;/code&gt;, &lt;code&gt;submissionUrl&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Tender documents and e-submission links&lt;/td&gt;
&lt;td&gt;ec.europa.eu links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;isCorrection&lt;/code&gt;, &lt;code&gt;previousDeadline&lt;/code&gt;, &lt;code&gt;deadlineChanged&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Correction tracking&lt;/td&gt;
&lt;td&gt;&lt;code&gt;True&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;open / closed / awarded&lt;/td&gt;
&lt;td&gt;&lt;code&gt;open&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Award notices add winners (with country and company IDs), award value, number of bids and lowest/highest bid. I left awards out of this run to keep it short.&lt;/p&gt;

&lt;p&gt;A few things from the 18 notices that are hard to see in the TED UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They came from 9 countries. Belgium had 7, Italy 3, Poland 2, and Finland, Albania, Czechia, Greece, Romania and France one each.&lt;/li&gt;
&lt;li&gt;They were written in 8 languages. Five were in Dutch, so a keyword search in English alone still catches non-English notices here, but the README suggests adding the word in the buyer's language too.&lt;/li&gt;
&lt;li&gt;11 of 18 had a published value. The median was €459,036. The largest was a €700M European Commission framework for financial IT systems, split into 2 lots.&lt;/li&gt;
&lt;li&gt;Deadlines ranged from 1 to 47 days away, median 22. Three notices had a deadline that moved since the first version, and the actor flags that with &lt;code&gt;deadlineChanged&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;All 18 had both a documents link and an e-submission link.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Main input options
&lt;/h2&gt;

&lt;p&gt;You don't need all 30-odd settings. These cover most searches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;keywords&lt;/strong&gt;: full-text search in title, description and lots. &lt;code&gt;keywordMode&lt;/code&gt; switches between any and all. &lt;code&gt;excludeKeywords&lt;/code&gt; drops noise like &lt;code&gt;window cleaning&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;noticeStages&lt;/strong&gt;: &lt;code&gt;competition&lt;/code&gt; (open tenders), awards, or planning notices. Planning gives you a heads-up months before the tender.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;countries&lt;/strong&gt; and &lt;strong&gt;placeOfPerformance&lt;/strong&gt;: buyer country, or a NUTS code like &lt;code&gt;PL9&lt;/code&gt; for Masovia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cpvCodes&lt;/strong&gt;: CPV prefixes. &lt;code&gt;72&lt;/code&gt; is IT services, &lt;code&gt;45&lt;/code&gt; construction, &lt;code&gt;33&lt;/code&gt; medical equipment. This is language-independent, so it is more reliable than keywords for broad sectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;minValue / maxValue&lt;/strong&gt;: filter by estimated value. Notices without a value are excluded when you set these.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onlyOpen&lt;/strong&gt; and &lt;strong&gt;deadlineWithinDays&lt;/strong&gt;: only tenders you can still bid on, or only those closing within N days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;publishedWithin&lt;/strong&gt; or &lt;strong&gt;publishedFrom / publishedTo&lt;/strong&gt;: the date window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;includeBuyerHistory&lt;/strong&gt;: for each tender, the buyer's past awards in the same sector, likely incumbent, top winners and average number of bids. This is charged separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aiEnrichment&lt;/strong&gt; with &lt;strong&gt;companyProfile&lt;/strong&gt;: translation into your language, a short summary, key requirements and a 0 to 100 fit score. Also charged separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onlyNew&lt;/strong&gt; with &lt;strong&gt;monitorId&lt;/strong&gt;: for scheduled runs, return only notices you haven't received before.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;maxResults&lt;/strong&gt;: the cap. I used 40.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvdij3mzsrfz1w99cjuo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvdij3mzsrfz1w99cjuo.png" alt="Input schema of the EU Tenders Scraper" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/flarewow/eu-tenders-ted-scraper" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. You need an Apify account; the free plan is enough for a test.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Keywords&lt;/strong&gt;, type your search. I used &lt;code&gt;cybersecurity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Under notice stages keep &lt;strong&gt;Tenders&lt;/strong&gt;. Switch on &lt;strong&gt;Only open tenders&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Published within&lt;/strong&gt; to a month and &lt;strong&gt;Max results&lt;/strong&gt; to 40.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;. My run finished in under 5 seconds.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Output&lt;/strong&gt; tab. Export to CSV, Excel or JSON, or send it straight to Google Sheets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the table is too wide, the export dialog lets you pick columns. I usually keep title, buyer, country, value, deadline and the two links.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the actor and load the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keywords&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cybersecurity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noticeStages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;competition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publishedWithin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;month&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onlyOpen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxResults&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flarewow/eu-tenders-ted-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noticeId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buyerName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buyerCountry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpvLabel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimatedValueEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daysToDeadline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;shortlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daysToDeadline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shortlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buyerCountry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;value_counts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Median value (EUR):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimatedValueEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;shortlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ted_cyber_open.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the token in an environment variable, not in the script. On my 18 rows &lt;code&gt;value_counts()&lt;/code&gt; printed BE 7, IT 3, PL 2 and six countries with 1, and the median came out at 459036.0. pandas skips the 7 empty values when it computes the median.&lt;/p&gt;

&lt;p&gt;One small thing: &lt;code&gt;estimatedValueEur&lt;/code&gt; is already converted with ECB reference rates, so you can sort Polish and Czech notices next to euro ones without doing the maths yourself. Use &lt;code&gt;currency&lt;/code&gt; and &lt;code&gt;estimatedValue&lt;/code&gt; if you need the original figure.&lt;/p&gt;

&lt;p&gt;If you bid on single lots, set &lt;code&gt;"splitLots": True&lt;/code&gt;. Each lot becomes its own row with its own value. Each row then counts as one notice for billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and integrations
&lt;/h2&gt;

&lt;p&gt;For a daily alert, set &lt;code&gt;onlyNew&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and give the search a &lt;code&gt;monitorId&lt;/code&gt; such as &lt;code&gt;cyber-eu&lt;/code&gt;. Then create a schedule in Apify Console (Schedules, daily at 7:00, for example). Each run returns only notices that weren't delivered before, and you aren't charged twice for the same one.&lt;/p&gt;

&lt;p&gt;From there you can push results to Google Sheets, Slack, Make, Zapier, n8n or any webhook. I send the CSV to a sheet and let a filter view do the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;The actor uses pay-per-event pricing. At the time of writing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free plan&lt;/th&gt;
&lt;th&gt;Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Notice&lt;/td&gt;
&lt;td&gt;$6.00 per 1,000&lt;/td&gt;
&lt;td&gt;$4.50 per 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buyer intelligence&lt;/td&gt;
&lt;td&gt;$0.020 per tender&lt;/td&gt;
&lt;td&gt;$0.015 per tender&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI analysis&lt;/td&gt;
&lt;td&gt;$0.030 per notice&lt;/td&gt;
&lt;td&gt;$0.020 per notice&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;My 18 notices came to $0.108 at the free-plan rate. Tender to award linking and EUR conversion are free. Check the actor page for current prices before a big job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;TED is official EU open data, published for re-use, and the actor reads it through the official TED API. That said, notices can contain the name, email or phone of a contact person at the buyer. Treat those as personal data under GDPR. Use them to respond to the tender, don't build marketing lists from them, and leave them out of anything you publish. In the screenshot above I left the contact fields out.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>webscraping</category>
      <category>opendata</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to scrape OLX.pl apartment listings with price per m into Python and pandas</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Wed, 28 Oct 2026 08:25:15 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-olxpl-apartment-listings-with-price-per-m2-into-python-and-pandas-4ia3</link>
      <guid>https://dev.to/norbertso/how-to-scrape-olxpl-apartment-listings-with-price-per-m2-into-python-and-pandas-4ia3</guid>
      <description>&lt;p&gt;Polish property portals don't offer a public export button, and OLX.pl is one of the biggest sources of apartment listings in the country. If you want asking prices per square metre for a district, or a daily feed of fresh listings for an agency CRM, you need the data in a table first.&lt;/p&gt;

&lt;p&gt;This guide uses the &lt;a href="https://apify.com/flarewow/olx-nieruchomosci-pl" rel="noopener noreferrer"&gt;OLX Real Estate Scraper&lt;/a&gt; on Apify. I ran it while writing this post with a small search: 2-room apartments for sale in Kraków, capped at 50 listings. The run finished in 5.5 seconds. Every number below comes from that dataset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn3pgnq7fy2x7a9vgdn3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn3pgnq7fy2x7a9vgdn3b.png" alt="OLX real estate data from Kraków in a table" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get per listing
&lt;/h2&gt;

&lt;p&gt;One listing becomes one row. These are the fields I got back:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example from the run&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2-room flat ad title&lt;/td&gt;
&lt;td&gt;As written by the advertiser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;price&lt;/code&gt;, &lt;code&gt;currency&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;607034, PLN&lt;/td&gt;
&lt;td&gt;Asking price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pricePerM2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16147.0&lt;/td&gt;
&lt;td&gt;Calculated by the scraper from price and area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;areaM2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;40.0&lt;/td&gt;
&lt;td&gt;Floor area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rooms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"2 pokoje"&lt;/td&gt;
&lt;td&gt;Polish label from OLX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;floor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"5"&lt;/td&gt;
&lt;td&gt;Can be null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;market&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pierwotny / Wtórny&lt;/td&gt;
&lt;td&gt;Primary (developer) or secondary market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;buildingType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blok, Apartamentowiec, Kamienica&lt;/td&gt;
&lt;td&gt;Block, apartment building, tenement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;furnished&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tak / Nie&lt;/td&gt;
&lt;td&gt;Yes / No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isBusiness&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;Agency or developer vs private owner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(empty in my run)&lt;/td&gt;
&lt;td&gt;Treat as personal data, see below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;city&lt;/code&gt;, &lt;code&gt;district&lt;/code&gt;, &lt;code&gt;region&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Kraków, Podgórze, Małopolskie&lt;/td&gt;
&lt;td&gt;District was missing on 3 of 50 rows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lat&lt;/code&gt;, &lt;code&gt;lon&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;50.09, 19.93&lt;/td&gt;
&lt;td&gt;Map coordinates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ISO timestamp&lt;/td&gt;
&lt;td&gt;When the ad was posted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;photos&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Description comes as HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In monitoring mode two extra fields appear: &lt;code&gt;changeType&lt;/code&gt; (new listing or price change) and &lt;code&gt;previousPrice&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the 50 Kraków listings looked like
&lt;/h2&gt;

&lt;p&gt;It's a small sample from one morning, so don't read too much into it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Median asking price: 607,034 PLN. Cheapest 420,000, most expensive 1,210,023.&lt;/li&gt;
&lt;li&gt;Median price per m²: 16,147 PLN. The range was wide, from 11,598 to 27,900.&lt;/li&gt;
&lt;li&gt;Area: 30 to 69 m², median 40.&lt;/li&gt;
&lt;li&gt;22 listings were primary market and 28 secondary. Primary flats had a median of 16,650 PLN/m², secondary ones 15,040.&lt;/li&gt;
&lt;li&gt;43 of 50 ads came from businesses. Only 7 were private owners.&lt;/li&gt;
&lt;li&gt;Podgórze had the most listings (9), then Prądnik Biały (7).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That 43 to 7 split is something you only notice once the data is in a dataframe. If you build lead lists for an agency, the &lt;code&gt;ownerType&lt;/code&gt; filter matters a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The main input options
&lt;/h2&gt;

&lt;p&gt;The input form is in Polish, because the actor was built for Polish agencies. The values you will touch most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subcategory&lt;/code&gt;: &lt;code&gt;mieszkania&lt;/code&gt; (apartments), &lt;code&gt;domy&lt;/code&gt; (houses), &lt;code&gt;dzialki&lt;/code&gt; (plots), &lt;code&gt;biura-lokale&lt;/code&gt; (offices and retail), &lt;code&gt;garaze-parkingi&lt;/code&gt; (garages), &lt;code&gt;stancje-pokoje&lt;/code&gt; (rooms).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;transaction&lt;/code&gt;: &lt;code&gt;sprzedaz&lt;/code&gt; (sale), &lt;code&gt;wynajem&lt;/code&gt; (rent) or &lt;code&gt;zamiana&lt;/code&gt; (swap).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;city&lt;/code&gt; plus &lt;code&gt;radiusKm&lt;/code&gt; (0, 5, 10, 15, 30, 50, 75 or 100). City Kraków with 30 km picks up the surrounding towns too, which helps for houses and plots.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;district&lt;/code&gt;: optional, narrows to one district.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;priceMin&lt;/code&gt;, &lt;code&gt;priceMax&lt;/code&gt;, &lt;code&gt;areaMin&lt;/code&gt;, &lt;code&gt;areaMax&lt;/code&gt; and for plots &lt;code&gt;plotAreaMin&lt;/code&gt;, &lt;code&gt;plotAreaMax&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rooms&lt;/code&gt;: list with &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;two&lt;/code&gt;, &lt;code&gt;three&lt;/code&gt;, &lt;code&gt;four&lt;/code&gt; (four means 4 or more).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;buildingType&lt;/code&gt;, &lt;code&gt;floor&lt;/code&gt;, &lt;code&gt;market&lt;/code&gt; (&lt;code&gt;primary&lt;/code&gt; / &lt;code&gt;secondary&lt;/code&gt;), &lt;code&gt;furniture&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ownerType&lt;/code&gt;: &lt;code&gt;private&lt;/code&gt; or &lt;code&gt;business&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;postedWithin&lt;/code&gt;: &lt;code&gt;24h&lt;/code&gt;, &lt;code&gt;7d&lt;/code&gt;, &lt;code&gt;30d&lt;/code&gt; or &lt;code&gt;all&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxItems&lt;/code&gt;: a cost cap per run. Default is 500.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchUrls&lt;/code&gt;: paste search links copied from OLX.pl. They override every filter above.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/flarewow/olx-nieruchomosci-pl" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click Try for free. You need a free Apify account.&lt;/li&gt;
&lt;li&gt;Pick the category and transaction type. I used apartments for sale.&lt;/li&gt;
&lt;li&gt;Type the city and choose room count. Set Max items to something small for the first try, I used 50.&lt;/li&gt;
&lt;li&gt;Click Start. My run took a few seconds.&lt;/li&gt;
&lt;li&gt;Open the Output tab and export to CSV, Excel or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvadpwmn7t1wsg6mclead.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvadpwmn7t1wsg6mclead.png" alt="The input form with filters for category, city and price" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you already have a search open on OLX with all the filters you like, copy its URL into the advanced &lt;code&gt;searchUrls&lt;/code&gt; field. Faster than rebuilding it field by field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the actor and load the results. Your API token is under Settings &amp;gt; API &amp;amp; Integrations in the Apify Console. Keep it in an environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subcategory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mieszkania&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transaction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sprzedaz&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Kraków&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rooms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;two&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxItems&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flarewow/olx-nieruchomosci-pl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;listings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median price/m2:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricePerM2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricePerM2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;district&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;value_counts&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;krakow_2_rooms.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my dataset this printed 50 listings, a median of 16,147 PLN/m² and the primary vs secondary split shown earlier. I drop &lt;code&gt;sellerName&lt;/code&gt; right after loading because I don't need it for price analysis and I'd rather not store it.&lt;/p&gt;

&lt;p&gt;A quick per-district view is one line more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;district&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;district&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;median_m2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricePerM2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;listings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With 50 rows most districts have 2 to 4 listings, so raise &lt;code&gt;maxItems&lt;/code&gt; before you draw conclusions per district.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and monitoring new listings
&lt;/h2&gt;

&lt;p&gt;The part agencies use most is monitoring. Set &lt;code&gt;monitorNew&lt;/code&gt; to true and the actor remembers which listings it has already seen for that search. The first run builds the baseline. After that, each run returns only listings that are new since the last one. With &lt;code&gt;detectPriceChanges&lt;/code&gt; on (the default) it also flags price drops and rises on listings it already knows, with the old price in &lt;code&gt;previousPrice&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make that useful, add a schedule in the Apify Console (Schedules tab): hourly for a busy city, daily for a small town. From there the results can go to Google Sheets, Slack, Make, Zapier, n8n or a webhook. The actor also works through the Apify MCP server, so you can call it from Claude, ChatGPT or Cursor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;The actor is pay per event. Current prices per 1,000 scraped listings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Apify plan&lt;/th&gt;
&lt;th&gt;Per 1,000 listings&lt;/th&gt;
&lt;th&gt;Per 1,000 new listings (monitoring)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$8&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bronze&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;td&gt;$12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Silver&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gold and above&lt;/td&gt;
&lt;td&gt;$4&lt;/td&gt;
&lt;td&gt;$8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Price changes in monitoring mode cost the same as a scraped listing. There is also a $0.05 charge per run start, and the first 100 listings are free for a new user. So a 50-listing test like mine fits inside the free allowance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The scraper reads public listing data through the same JSON API the OLX app uses. Some ads come from private owners, and fields like &lt;code&gt;sellerName&lt;/code&gt; or the free-text &lt;code&gt;description&lt;/code&gt; can contain personal data. Under GDPR (RODO in Poland) you need a legal basis to store and process that. For price research, drop those columns right away, as in the code above. For lead generation, the &lt;code&gt;ownerType: business&lt;/code&gt; filter keeps you to agencies and developers. Keep &lt;code&gt;maxItems&lt;/code&gt; reasonable and don't hammer the site with schedules every few minutes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>realestate</category>
      <category>datascience</category>
    </item>
    <item>
      <title>How to track Allegro prices from every seller by EAN barcode with Python</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Mon, 26 Oct 2026 08:30:45 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-track-allegro-prices-from-every-seller-by-ean-barcode-with-python-25k8</link>
      <guid>https://dev.to/norbertso/how-to-track-allegro-prices-from-every-seller-by-ean-barcode-with-python-25k8</guid>
      <description>&lt;p&gt;If you sell on Allegro or buy stock for resale in Poland, the question you ask every week is simple: who else sells this exact product, and at what price? Searching by product name gets messy fast. Searching by EAN barcode is cleaner, because one barcode should point to one product card on Allegro, and that card lists every seller.&lt;/p&gt;

&lt;p&gt;This tutorial shows how to pull that seller list for a batch of EAN codes with the &lt;a href="https://apify.com/liveclaude/allegro-ean-price-tracker" rel="noopener noreferrer"&gt;Allegro EAN Price Tracker&lt;/a&gt; on Apify. First without code, then from Python with pandas. Every number below comes from one test run I did on 4 barcodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbjj4lfd1yle3isgacyf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbjj4lfd1yle3isgacyf4.png" alt="Allegro EAN Price Tracker output table" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the test run returned
&lt;/h2&gt;

&lt;p&gt;Input: 4 EAN codes, Allegro.pl, up to 10 offers per product, cheapest first, one row per offer.&lt;/p&gt;

&lt;p&gt;The run took 241 seconds and returned 24 rows: 23 seller offers plus 1 row for a barcode Allegro did not know.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;EAN&lt;/th&gt;
&lt;th&gt;Product on Allegro&lt;/th&gt;
&lt;th&gt;Offers&lt;/th&gt;
&lt;th&gt;Lowest&lt;/th&gt;
&lt;th&gt;Highest&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;195949036842&lt;/td&gt;
&lt;td&gt;Apple iPhone 15 6 GB / 256 GB 5G, black&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1,400.00 PLN&lt;/td&gt;
&lt;td&gt;3,173.90 PLN&lt;/td&gt;
&lt;td&gt;2,040.49 PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5702017584072&lt;/td&gt;
&lt;td&gt;LEGO Technic 42173 Koenigsegg Jesko Absolut&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;175.67 PLN&lt;/td&gt;
&lt;td&gt;419.90 PLN&lt;/td&gt;
&lt;td&gt;265.19 PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5449000000996&lt;/td&gt;
&lt;td&gt;5 l PET bottle listing&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;4.00 PLN&lt;/td&gt;
&lt;td&gt;4.00 PLN&lt;/td&gt;
&lt;td&gt;4.00 PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5900084231472&lt;/td&gt;
&lt;td&gt;not found&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few things stood out. The iPhone spread is huge, more than 1,700 PLN between the cheapest and the most expensive offer for the same product card. Of those 10 iPhone offers, 9 had Allegro Smart! delivery, 6 came from Super Sellers and 3 were promoted placements. The most expensive one carried the Lowest Price Guarantee badge and a 12-day delivery time.&lt;/p&gt;

&lt;p&gt;The third barcode is a good warning. I used the example code from the actor's input description and it matched a listing for a 5-litre PET bottle. Always read &lt;code&gt;productName&lt;/code&gt; before you trust a row.&lt;/p&gt;

&lt;h2&gt;
  
  
  What data you get
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;outputFormat: "offers"&lt;/code&gt; you get one flat row per seller offer. These are the fields I found most useful:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The barcode you sent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;productName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of the Allegro product card the EAN matched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The seller's own offer title&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;price&lt;/code&gt; / &lt;code&gt;priceWithDelivery&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Item price and price including the cheapest delivery, in PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deliveryTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delivery text as Allegro shows it, e.g. "dostawa jutro"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;smart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Offer has Allegro Smart! delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;superSeller&lt;/code&gt; / &lt;code&gt;sellerRating&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Super Seller badge and positive rating in percent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerIsCompany&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whether the seller account is a business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;promoted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sponsored placement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lowestPriceGuarantee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Offer has the "Gwarancja najniższej ceny" badge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;productRating&lt;/code&gt; / &lt;code&gt;productReviewsCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Product card rating and review count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link to the offer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Barcodes that match nothing come back as a row with &lt;code&gt;found: false&lt;/code&gt; and a &lt;code&gt;note&lt;/code&gt;. In my run that note read "No Allegro product with this EAN (Allegro only showed similar products)."&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;outputFormat: "products"&lt;/code&gt; (the default) you get one record per EAN instead, with &lt;code&gt;lowestPrice&lt;/code&gt;, &lt;code&gt;highestPrice&lt;/code&gt;, &lt;code&gt;avgPrice&lt;/code&gt;, &lt;code&gt;offerCount&lt;/code&gt; and the offers nested in an &lt;code&gt;offers[]&lt;/code&gt; array. Use that when you only care about the price range per product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/allegro-ean-price-tracker" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste your barcodes into &lt;strong&gt;EAN / GTIN codes&lt;/strong&gt;, one per line.&lt;/li&gt;
&lt;li&gt;Pick the marketplace. Allegro.pl is the default, Allegro.cz and Allegro.sk are also supported.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Top N offers per product&lt;/strong&gt;. The default is 20, the maximum is 500.&lt;/li&gt;
&lt;li&gt;Choose the output format and click &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When the run finishes, export the dataset as Excel, CSV or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmgrr0n8ts4xai04c8yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmgrr0n8ts4xai04c8yg.png" alt="Input form of the Allegro EAN Price Tracker" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main input options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;topNOffers&lt;/code&gt;: how many seller offers per product.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sortBy&lt;/code&gt;: &lt;code&gt;price-asc&lt;/code&gt;, &lt;code&gt;price-desc&lt;/code&gt; or &lt;code&gt;rating-desc&lt;/code&gt;. In my run the dataset rows did not come out in price order, so sort again on your side.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;smartFilter&lt;/code&gt;: &lt;code&gt;all&lt;/code&gt;, &lt;code&gt;smart-only&lt;/code&gt; or &lt;code&gt;exclude-smart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;includePromoted&lt;/code&gt;: set to &lt;code&gt;false&lt;/code&gt; to drop sponsored offers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;detectHiddenDiscounts&lt;/code&gt;: for offers with the Lowest Price Guarantee badge, it adds the price the seller actually set (&lt;code&gt;realSellerPrice&lt;/code&gt;) and how much Allegro covers. This one is billed per checked offer, so leave it off unless you need it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onlyChanges&lt;/code&gt; with &lt;code&gt;monitorId&lt;/code&gt;: monitoring mode, explained below.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the actor and load the results into a DataFrame. You need your Apify API token from the Integrations page in the Apify Console. Keep it in an environment variable, not in the script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eans&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;195949036842&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5702017584072&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5449000000996&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5900084231472&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;topNOffers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sortBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-asc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smartFilter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;includePromoted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outputFormat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/allegro-ean-price-tracker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Barcodes Allegro did not recognise
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not found:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;offers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;notna&lt;/span&gt;&lt;span class="p"&gt;()].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;productName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;offers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;lowest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;highest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;smart_share&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allegro_ean_prices.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One cleanup step is worth adding. On the iPhone card, some offer titles mentioned ex-display units ("Powystawowy"), condition notes ("Stan: bardzo dobry") or even a different variant (one said 15 Plus, another 128GB). Sellers attach offers to product cards loosely, so filter titles before you compare prices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;noise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;powystaw|stan:|używan|kondycja|plus|128gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;noise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;na&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;cheapest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceWithDelivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cheapest&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceWithDelivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;superSeller&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the pattern for your product category. For LEGO sets you will want different words than for phones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and price alerts
&lt;/h2&gt;

&lt;p&gt;For ongoing tracking, turn on &lt;code&gt;onlyChanges&lt;/code&gt; and give the watch list a &lt;code&gt;monitorId&lt;/code&gt;, for example &lt;code&gt;competitors-lego&lt;/code&gt;. Then add a schedule in Apify, say every morning at 7:00. Each run returns only new sellers and offers whose price changed since the previous run, with &lt;code&gt;previousPrice&lt;/code&gt;, &lt;code&gt;priceChange&lt;/code&gt; and &lt;code&gt;priceChangePercent&lt;/code&gt;. According to the actor's README, unchanged offers are not charged.&lt;/p&gt;

&lt;p&gt;From there you can push results to Google Sheets, Slack, email, Make, Zapier or n8n through Apify integrations, or poll the dataset from your own repricing script. Use a separate &lt;code&gt;monitorId&lt;/code&gt; per list so the change history stays clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing per 1,000 results
&lt;/h2&gt;

&lt;p&gt;The actor uses pay per event. Current prices on the Free plan, with the Business plan price in brackets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product resolved by EAN: $10 per 1,000 EANs ($7 on Business)&lt;/li&gt;
&lt;li&gt;Seller offer: $2 per 1,000 offers ($1.50 on Business)&lt;/li&gt;
&lt;li&gt;EAN not found: $1 per 1,000&lt;/li&gt;
&lt;li&gt;Hidden discount check: $10 per 1,000 checked offers, only if you enable it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So 1,000 barcodes with 10 offers each would come to roughly $10 for products plus $20 for 10,000 offers on the Free plan, before the small per-run start fee. Matched products are cached for 24 hours, which helps if you rerun the same list the same day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The actor reads publicly visible offer data. In my run all 23 offers came from business accounts, but Allegro also has private sellers, and a seller login can be a person's nickname. If you store or share results, drop or mask &lt;code&gt;sellerLogin&lt;/code&gt; and &lt;code&gt;sellerUrl&lt;/code&gt; unless you have a reason and a legal basis to keep them, and handle any personal data under GDPR. Keep run frequency sensible: once or twice a day is plenty for price monitoring.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>webscraping</category>
      <category>ecommerce</category>
      <category>pandas</category>
    </item>
    <item>
      <title>How to scrape Kleinanzeigen.de listings by city and radius with Python</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Thu, 22 Oct 2026 07:31:09 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-kleinanzeigende-listings-by-city-and-radius-with-python-5b9b</link>
      <guid>https://dev.to/norbertso/how-to-scrape-kleinanzeigende-listings-by-city-and-radius-with-python-5b9b</guid>
      <description>&lt;p&gt;Kleinanzeigen.de, formerly eBay Kleinanzeigen, is Germany's biggest classifieds site. People sell bikes, cars, furniture and flats there. The site itself only shows 25 listings per page and stops after 50 pages. For a price check or a daily alert you want the data in a table. This post walks through the &lt;a href="https://apify.com/liveclaude/kleinanzeigen-scraper" rel="noopener noreferrer"&gt;Kleinanzeigen Scraper&lt;/a&gt; on Apify, first without code and then from Python.&lt;/p&gt;

&lt;p&gt;My test search: &lt;code&gt;e-bike&lt;/code&gt; within 20 km of Berlin, newest first, capped at 40 listings. Every number below is from that run on 22 October 2026.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrn1m238ihwm3u46jzhh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrn1m238ihwm3u46jzhh.png" alt="Kleinanzeigen Scraper results for e-bike listings around Berlin" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the run returned
&lt;/h2&gt;

&lt;p&gt;Kleinanzeigen reported 2,208 matching listings for that search. I only took the newest 40, which covered roughly 12 and a half hours of posts (the oldest timestamped one was from 18:54 UTC the evening before, the newest from 07:20 UTC). Expect a busy category in a big city to fill up fast.&lt;/p&gt;

&lt;p&gt;The price summary row gave me this for the 33 listings it analysed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Min&lt;/td&gt;
&lt;td&gt;2 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25th percentile&lt;/td&gt;
&lt;td&gt;850 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median&lt;/td&gt;
&lt;td&gt;1,899 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average&lt;/td&gt;
&lt;td&gt;2,002.55 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75th percentile&lt;/td&gt;
&lt;td&gt;2,499 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max&lt;/td&gt;
&lt;td&gt;6,599 EUR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negotiable (VB)&lt;/td&gt;
&lt;td&gt;12.12%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price reduced&lt;/td&gt;
&lt;td&gt;3.03%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shipping offered&lt;/td&gt;
&lt;td&gt;72.73%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The top location was Lichtenberg with 16 listings, far ahead of every other district. Most of those came from shops, which brings me to the first lesson: 24 of the 40 listings were from PRO (commercial) sellers, and 4 were promoted TOP ads.&lt;/p&gt;

&lt;p&gt;The 2 EUR minimum was a luggage strap, which matched "e-bike" somewhere in its text. More on filtering that out below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fields you get per listing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example from this run&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Giant Explore E+ 2 STA amber glow XL E-Bike&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;price&lt;/code&gt;, &lt;code&gt;priceType&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;1999, fixed&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;negotiable&lt;/code&gt; for VB listings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;originalPrice&lt;/code&gt;, &lt;code&gt;priceReduced&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Filled when the seller cut the price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;location&lt;/code&gt;, &lt;code&gt;postalCode&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Friedrichshain, 10243&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;distanceKm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Distance from your search location&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;postedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-22T06:08:00Z&lt;/td&gt;
&lt;td&gt;Missing on some TOP ads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;shippingAvailable&lt;/code&gt;, &lt;code&gt;buyNow&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;"Versand möglich", "Direkt kaufen"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isTopAd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;Promoted listing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sellerType&lt;/code&gt;, &lt;code&gt;isProSeller&lt;/code&gt;, &lt;code&gt;shopName&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;commercial, true, Radwelt Mitte RWM 1 GmbH&lt;/td&gt;
&lt;td&gt;Shop name only for PRO sellers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mileageKm&lt;/code&gt;, &lt;code&gt;firstRegistration&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Cars, already in search results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;livingSpaceM2&lt;/code&gt;, &lt;code&gt;rooms&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Real estate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;imageUrl&lt;/code&gt;, &lt;code&gt;imageCount&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With &lt;strong&gt;Listing details&lt;/strong&gt; on, you also get the full description, all attributes (brand, model, frame size and so on), the equipment list, all photos and GPS coordinates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/kleinanzeigen-scraper" rel="noopener noreferrer"&gt;Kleinanzeigen Scraper&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. A free Apify account is enough. You do not need a Kleinanzeigen login or your own proxies.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;e-bike&lt;/code&gt; into &lt;strong&gt;Search terms&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Location&lt;/strong&gt; to &lt;code&gt;Berlin&lt;/code&gt; and &lt;strong&gt;Radius&lt;/strong&gt; to 20 km. Postcodes like &lt;code&gt;80331&lt;/code&gt; work too.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Max. listings per search&lt;/strong&gt; to 40.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;suche&lt;/code&gt; and &lt;code&gt;defekt&lt;/code&gt; to &lt;strong&gt;Exclude words&lt;/strong&gt;. That drops "looking for" posts and broken bikes, and filtered listings are free.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Price summary per search&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;. Then open the &lt;strong&gt;Listings&lt;/strong&gt; or &lt;strong&gt;Price summaries&lt;/strong&gt; view, or export CSV, Excel or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmm2io3cwwe42v5fqawj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmm2io3cwwe42v5fqawj.png" alt="Input form of the Kleinanzeigen Scraper on Apify" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Input options worth knowing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kleinanzeigen URLs&lt;/strong&gt;: set filters on kleinanzeigen.de in your browser and paste the link. Category-specific filters (mileage, first registration, rooms, living space, brand) stay in the URL and the scraper keeps them. Single listings, seller pages and PRO shops work as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Categories&lt;/strong&gt;: limit keywords to one or more categories. Picking the e-bike category would have kept my luggage strap out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Title must include (any)&lt;/strong&gt;: keep only listings whose title has one of your words. Also a fix for the strap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Min. / Max. price&lt;/strong&gt;: a 100 EUR floor removes most accessories in one go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listing type&lt;/strong&gt;: offers, wanted ads, or both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seller type&lt;/strong&gt;: private or commercial. Useful here, since shops dominated the results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shipping&lt;/strong&gt; and &lt;strong&gt;Only "Direkt kaufen"&lt;/strong&gt;: shipping only, pickup only, or buy-now listings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Posted within (hours)&lt;/strong&gt;: for example &lt;code&gt;24&lt;/code&gt;. The search stops once it reaches older listings, so daily runs stay cheap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only price-reduced listings&lt;/strong&gt;: listings where the seller crossed out an older price.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include TOP ads&lt;/strong&gt;: switch off for organic results only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get more than 1,250 results&lt;/strong&gt;: on by default. Big searches are split into price ranges to get past the 50 page limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sellers to track&lt;/strong&gt;: user IDs, seller links or PRO shop names, with their profile and active listings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;e-bike&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Berlin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;radiusKm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;20&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxItemsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;excludeKeywords&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;suche&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defekt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceSummary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/kleinanzeigen-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;listings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;listing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# shops carry sellerType "commercial"; other listings have no shop attached
&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seller&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;fillna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no shop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bikes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bikes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seller&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="n"&gt;bikes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ebikes_berlin.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;radiusKm&lt;/code&gt; is a string. The input form offers fixed values (0, 1, 2, 3, 5, 10, 15, 20, 30, 50, 100, 150, 200).&lt;/p&gt;

&lt;p&gt;Output from my run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            count  median     min     max
seller
commercial     23  2499.0  1590.0  6599.0
no shop        12   815.0   249.0  2000.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That split tells you more than the overall median. Shops in this search started at 1,590 EUR and sat around 2,499 EUR. Listings without a shop had a median of 815 EUR. If you are hunting for a used e-bike, set &lt;strong&gt;Seller type&lt;/strong&gt; to private and the overall 1,899 EUR median stops being misleading.&lt;/p&gt;

&lt;p&gt;Two listings were below 100 EUR and the filter dropped them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and alerts
&lt;/h2&gt;

&lt;p&gt;The scraper has a monitoring mode built for alerts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save your input as a task.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Only new listings (monitoring)&lt;/strong&gt;. Later runs return only listings you have not seen, plus price drops.&lt;/li&gt;
&lt;li&gt;Keep &lt;strong&gt;Detect sold / reserved / deleted listings&lt;/strong&gt; on. Listings that vanish are reported as &lt;code&gt;sold&lt;/code&gt;, &lt;code&gt;reserved&lt;/code&gt; or &lt;code&gt;removed&lt;/code&gt;, with &lt;code&gt;daysOnMarket&lt;/code&gt;. Every record has &lt;code&gt;listingStatus&lt;/code&gt; so you can route them.&lt;/li&gt;
&lt;li&gt;Combine with &lt;strong&gt;Posted within (hours)&lt;/strong&gt; set to 2 or 24 and schedule hourly or daily.&lt;/li&gt;
&lt;li&gt;Give the task a &lt;strong&gt;Monitor name&lt;/strong&gt; like &lt;code&gt;ebikes-berlin&lt;/code&gt; if you run several monitors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For searches over 2,000 results, sold detection and older price drops only work after you narrow the search with a location, category or price range. My 2,208 result query would need a price band for that.&lt;/p&gt;

&lt;p&gt;Results can go to Google Sheets, Slack, Make, Zapier, n8n or any webhook, or you can call the scraper from an AI agent through the Apify MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing per 1,000 results
&lt;/h2&gt;

&lt;p&gt;Pay per event. Current prices per 1,000 events:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Starter&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Listing&lt;/td&gt;
&lt;td&gt;$1.30&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;td&gt;$1.05&lt;/td&gt;
&lt;td&gt;$0.90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listing details (optional)&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;td&gt;$1.10&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$0.90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seller / shop profile&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$1.80&lt;/td&gt;
&lt;td&gt;$1.60&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A price summary row costs about one cent and each run has a start fee of $0.00005. Filtered listings, already seen listings in monitoring mode and failed pages are free. At Free plan prices, my 40 listing run with one summary works out to roughly six cents. You can set a maximum cost per run and it stops there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;Many Kleinanzeigen sellers are private people. The scraper does not collect phone numbers or e-mail addresses of private sellers, and Kleinanzeigen hides them anyway. PRO shops publish business contact details on their shop pages, and only those end up in seller records. If you turn on seller profiles, you may get display names of private sellers too; leave them out of anything you publish or share, and keep in mind that GDPR covers storing them. Kleinanzeigen's terms apply to what you do with the data. Use small, targeted searches with filters and you will collect less data and pay less.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kleinanzeigen</category>
      <category>python</category>
      <category>webscraping</category>
      <category>germany</category>
    </item>
    <item>
      <title>How to compare eBay prices across countries with Python (UK vs Germany example)</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Thu, 22 Oct 2026 07:30:18 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-compare-ebay-prices-across-countries-with-python-uk-vs-germany-example-bli</link>
      <guid>https://dev.to/norbertso/how-to-compare-ebay-prices-across-countries-with-python-uk-vs-germany-example-bli</guid>
      <description>&lt;p&gt;Is a used Steam Deck OLED cheaper on ebay.de or on ebay.co.uk? I wanted a quick answer with real listings instead of scrolling two sites and converting currencies in my head. This post shows how I got it with the &lt;a href="https://apify.com/liveclaude/ebay-scraper" rel="noopener noreferrer"&gt;eBay Scraper&lt;/a&gt; on Apify: first with no code, then with a short Python script that loads everything into pandas.&lt;/p&gt;

&lt;p&gt;All numbers below come from one run on 22 October 2026: the query &lt;code&gt;steam deck oled&lt;/code&gt; on two sites, capped at 20 listings per site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrg07f30dgl9npa1mld7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrg07f30dgl9npa1mld7.png" alt="eBay Scraper results table for steam deck oled on ebay.de and ebay.co.uk" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the run returned
&lt;/h2&gt;

&lt;p&gt;The run saved 24 listings: 18 from ebay.de and 6 from ebay.co.uk. The UK search came back thinner than the German one, so treat the UK side as a small sample. On top of the listings, the scraper added two price summary rows (one per site) and one site comparison row.&lt;/p&gt;

&lt;p&gt;The summary rows did the currency work for me:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Site&lt;/th&gt;
&lt;th&gt;Listings&lt;/th&gt;
&lt;th&gt;Min&lt;/th&gt;
&lt;th&gt;Median&lt;/th&gt;
&lt;th&gt;Max&lt;/th&gt;
&lt;th&gt;Median in USD&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ebay.de&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;441 EUR&lt;/td&gt;
&lt;td&gt;640 EUR&lt;/td&gt;
&lt;td&gt;919.95 EUR&lt;/td&gt;
&lt;td&gt;718.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ebay.co.uk&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;419.99 GBP&lt;/td&gt;
&lt;td&gt;550 GBP&lt;/td&gt;
&lt;td&gt;618.70 GBP&lt;/td&gt;
&lt;td&gt;737.09&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The comparison row marked &lt;code&gt;de&lt;/code&gt; as the cheaper site, with a median spread of 18.11 USD. That gap is small. Condition matters more than the country here, as the pandas section shows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fields you get per listing
&lt;/h2&gt;

&lt;p&gt;These are the columns I used most. Every listing record has them, though some are empty when eBay does not show the value.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example from this run&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Valve Steam Deck OLED 512 GB Handheld Spielkonsole&lt;/td&gt;
&lt;td&gt;As shown on eBay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;price&lt;/code&gt;, &lt;code&gt;currency&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;450, EUR&lt;/td&gt;
&lt;td&gt;Local currency of the site&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;priceUsd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;505.53&lt;/td&gt;
&lt;td&gt;Converted, handy for cross-site work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;shippingCost&lt;/code&gt;, &lt;code&gt;totalPrice&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;7.69&lt;/td&gt;
&lt;td&gt;Total is price plus shipping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;condition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gebraucht&lt;/td&gt;
&lt;td&gt;In the site's language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;buyingFormat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;auction / buy-it-now&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bids&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;Auctions only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;watchers&lt;/code&gt;, &lt;code&gt;soldCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;17, 591&lt;/td&gt;
&lt;td&gt;Only when eBay displays them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;private / business&lt;/td&gt;
&lt;td&gt;Shown on sites like ebay.de&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sellerFeedbackPercent&lt;/code&gt;, &lt;code&gt;sellerFeedbackCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;100, 1090&lt;/td&gt;
&lt;td&gt;Seller reputation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;marketplace&lt;/code&gt;, &lt;code&gt;site&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;ebay.de, de&lt;/td&gt;
&lt;td&gt;Which eBay site it came from&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;epid&lt;/code&gt;, &lt;code&gt;imageUrl&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Product ID, photo, link&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every record also has &lt;code&gt;recordType&lt;/code&gt;: &lt;code&gt;item&lt;/code&gt; for a listing, &lt;code&gt;price-summary&lt;/code&gt; for the per-site stats, &lt;code&gt;site-comparison&lt;/code&gt; for the cross-site row. That one field makes filtering easy later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/ebay-scraper" rel="noopener noreferrer"&gt;eBay Scraper page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. You need a free Apify account. No eBay account is involved.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Search queries&lt;/strong&gt;, type &lt;code&gt;steam deck oled&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;eBay sites&lt;/strong&gt;, pick United Kingdom and Germany. There are 15 sites in total, and a switch to search all of them at once.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Max listings per search&lt;/strong&gt; to 20 while you test.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;case&lt;/code&gt;, &lt;code&gt;skin&lt;/code&gt; and &lt;code&gt;hülle&lt;/code&gt; to &lt;strong&gt;Exclude words in title&lt;/strong&gt;. Accessory listings drop out and you are not charged for them.&lt;/li&gt;
&lt;li&gt;Leave &lt;strong&gt;Price summary per search&lt;/strong&gt; on and turn on &lt;strong&gt;Compare prices between eBay sites&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;. My run finished in under a minute.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Price summaries&lt;/strong&gt; view for the numbers above, or export everything as CSV, Excel or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiy2lbxog36pe8k9dgzj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiy2lbxog36pe8k9dgzj9.png" alt="Input form of the eBay Scraper on Apify" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Input options worth knowing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;eBay URLs&lt;/strong&gt;: set filters on eBay in your browser and paste the link. Search pages, categories (&lt;code&gt;/b/...&lt;/code&gt;), stores, seller pages and single listings (&lt;code&gt;/itm/...&lt;/code&gt;) all work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filters in the form&lt;/strong&gt;: category ID, min and max price, condition (new, open box, refurbished, used, for parts), auction or Buy It Now, Best Offer only, free shipping only, item location, seller type, minimum seller feedback, sort order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Title must contain&lt;/strong&gt;: the opposite of exclude words. One UK result was titled "Valve Steam Deck 512GB Handheld Console - Black" with no "OLED" in it. Adding &lt;code&gt;oled&lt;/code&gt; here would have removed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listing details&lt;/strong&gt;: opens each listing and adds item specifics, brand, MPN, EAN/UPC, all photos and returns info. Costs extra, so only switch it on when you need those fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EAN / UPC codes&lt;/strong&gt;: search by barcode instead of keywords.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sellers&lt;/strong&gt;: give usernames to get a profile, active listings and recent buyer feedback with prices paid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only new listings&lt;/strong&gt;: monitoring mode, covered below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go past eBay's 10,000 result limit&lt;/strong&gt;: big searches get split into price ranges automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run this. Put your own API token from the Apify console in place of the placeholder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steam deck oled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sites&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxItemsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;excludeKeywords&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;case&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hülle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceSummary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compareSites&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/ebay-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;listings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;summaries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;by_condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by_condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalPrice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c1"&gt;# keep seller usernames out of files you share
&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steam_deck_ebay.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first print gave me this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                             count   median
marketplace condition
ebay.co.uk  Pre-owned            6  549.995
ebay.de     Gebraucht           11  599.900
            Neu                  4  734.475
            Neu (Sonstige)       3  630.000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So ebay.de had a mix of 11 used and 7 new or "new other" units, while all 6 UK listings were pre-owned. The German overall median of 640 EUR is pulled up by those new units at a median of 734.48 EUR. If you only care about used devices, the fair comparison is 599.90 EUR against 550 GBP.&lt;/p&gt;

&lt;p&gt;Shipping changes the picture a bit too. Median &lt;code&gt;totalPrice&lt;/code&gt; was 650.69 EUR on ebay.de and 562.47 GBP on ebay.co.uk. Two UK sellers charged 20 GBP for delivery, which is a lot on a 550 GBP item.&lt;/p&gt;

&lt;p&gt;Auctions are worth a separate look. Germany had 4 of them. Two had bids (15 bids at 441 EUR, 21 bids at 505 EUR) and two had none yet. Those prices will move until the auction ends, so do not mix them into a "typical price" without checking &lt;code&gt;timeLeft&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and integrations
&lt;/h2&gt;

&lt;p&gt;A one-off run answers one question. For price tracking, schedule it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save your input as a task in the Apify console.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Only new listings (monitoring)&lt;/strong&gt;. Each run then returns only listings it has not seen, plus price drops.&lt;/li&gt;
&lt;li&gt;Leave &lt;strong&gt;Track final prices of ended listings&lt;/strong&gt; on. When a tracked listing ends, the scraper opens its public page and records the final price, bids, end date and whether it sold. Each record carries &lt;code&gt;listingStatusChange&lt;/code&gt; with &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;price-drop&lt;/code&gt;, &lt;code&gt;sold&lt;/code&gt;, &lt;code&gt;ended-unsold&lt;/code&gt; or &lt;code&gt;removed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a schedule, for example daily at 07:00.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This matters because since July 2026 eBay shows sold and completed searches only to signed-in users. The scraper does not log in, so monitoring is how you collect real sale prices over time.&lt;/p&gt;

&lt;p&gt;For delivery, connect the dataset to Google Sheets, Make, Zapier, n8n or a webhook. You can also call &lt;code&gt;liveclaude/ebay-scraper&lt;/code&gt; from an AI agent through the Apify MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing per 1,000 results
&lt;/h2&gt;

&lt;p&gt;The scraper uses pay per event pricing. Current prices per 1,000 events:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Starter&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Listing&lt;/td&gt;
&lt;td&gt;$3.20&lt;/td&gt;
&lt;td&gt;$2.90&lt;/td&gt;
&lt;td&gt;$2.70&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listing details (optional)&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$4.50&lt;/td&gt;
&lt;td&gt;$4.20&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Description (optional)&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$4.50&lt;/td&gt;
&lt;td&gt;$4.20&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seller profile&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$4.50&lt;/td&gt;
&lt;td&gt;$4.20&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buyer feedback entry&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$2.20&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$1.80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A price summary or site comparison row costs about one cent each. Listings removed by your filters, already seen listings in monitoring mode and failed pages are free. My test run cost well under 10 cents. You can set a maximum cost per run in the run options and the scraper stops there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The scraper collects publicly visible listing data and does not use an eBay account or cookies. Search results can include seller usernames, and on eBay many sellers are private people. I drop &lt;code&gt;sellerName&lt;/code&gt; before saving or sharing anything, as in the script above, and work with feedback counts and seller type instead. If you store data on individuals, GDPR applies to you, and eBay's terms apply to how you use the data. Keep request volumes sensible and only collect what you need for the question you are answering.&lt;/p&gt;

&lt;p&gt;For my question the answer was short: used units sat around 600 EUR in Germany and 550 GBP in the UK. At that gap, shipping and condition decide which listing is the better deal.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ebay</category>
      <category>python</category>
      <category>webscraping</category>
      <category>pandas</category>
    </item>
    <item>
      <title>How to scrape Vinted listings and compare prices across countries with Python</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Wed, 21 Oct 2026 07:25:22 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-vinted-listings-and-compare-prices-across-countries-with-python-3493</link>
      <guid>https://dev.to/norbertso/how-to-scrape-vinted-listings-and-compare-prices-across-countries-with-python-3493</guid>
      <description>&lt;p&gt;Vinted runs 26 separate marketplaces, and the same jacket can show up on vinted.de, vinted.fr and vinted.it at once. If you resell, track second-hand prices or build a deal alert, you want that data in a table instead of 40 open browser tabs.&lt;/p&gt;

&lt;p&gt;This guide uses the &lt;a href="https://apify.com/liveclaude/vinted-scraper" rel="noopener noreferrer"&gt;Vinted Scraper&lt;/a&gt; on Apify. I ran it this morning with a small test: the query &lt;code&gt;levis 501&lt;/code&gt;, 25 newest listings each from Germany and France, plus the country price comparison switched on. It finished in about 15 seconds and returned 50 listings and one comparison row. Every number below comes from that run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwk5a3pnrp7e50px2mb6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwk5a3pnrp7e50px2mb6s.png" alt="Vinted listings for levis 501 exported to a table" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What data you get
&lt;/h2&gt;

&lt;p&gt;Each listing is one row. These are the fields I used most in the test run:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example from the run&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jean Levi's 501&lt;/td&gt;
&lt;td&gt;as written by the seller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;price&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;item price in local currency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;buyerProtectionFee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.45&lt;/td&gt;
&lt;td&gt;Vinted's buyer fee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;totalPrice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;37.45&lt;/td&gt;
&lt;td&gt;what a buyer actually pays before shipping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;priceEur&lt;/code&gt;, &lt;code&gt;totalPriceEur&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;35, 37.45&lt;/td&gt;
&lt;td&gt;converted to EUR for cross-country work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;brand&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;condition&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Levi's, EU 38, Très bon état&lt;/td&gt;
&lt;td&gt;condition comes in the marketplace language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;favouriteCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;a rough demand signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sellerIsBusiness&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;private seller vs Vinted Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;country&lt;/code&gt;, &lt;code&gt;marketplace&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;fr, vinted.fr&lt;/td&gt;
&lt;td&gt;where the listing was found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;photoUrls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;list of image URLs&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;url&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;link to the listing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recordType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;item&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;country-comparison&lt;/code&gt; for summary rows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Turn on &lt;strong&gt;Listing details&lt;/strong&gt; and you also get the full description, all photos, category path, colour, material, shipping price and sold/reserved status. &lt;strong&gt;Seller profiles&lt;/strong&gt; adds seller country, rating, review count, items sold and followers. Both cost extra per record, so leave them off until you need them.&lt;/p&gt;

&lt;p&gt;The comparison row is a separate record. For my query it held min, 25th percentile, median, average, 75th percentile and max price per country, the cheapest country and the link to the cheapest listing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the test run showed
&lt;/h2&gt;

&lt;p&gt;A few things stood out in the 50 rows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Median total price (item plus buyer fee) was 26.95 EUR on both sites. The cheapest listing cost 8.05 EUR on both.&lt;/li&gt;
&lt;li&gt;19 of the 25 listing IDs from vinted.de were also in the vinted.fr results. Vinted shows cross-border listings on EU sites, so "the German market" and "the French market" overlap a lot.&lt;/li&gt;
&lt;li&gt;44 listings came from private sellers and 6 from business accounts.&lt;/li&gt;
&lt;li&gt;41 of 50 had zero favourites. These were the newest listings, so that is expected.&lt;/li&gt;
&lt;li&gt;42 titles contained "501". The other 8 were other Levi's models (504, unlabeled jeans), because Vinted search is fuzzy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The overlap is the practical lesson. If you want to compare real local prices, use the &lt;strong&gt;Seller countries&lt;/strong&gt; filter or turn on seller profiles, so the comparison is grouped by where the seller is located instead of which domain the listing appeared on. The README says the same, and my run confirmed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/vinted-scraper" rel="noopener noreferrer"&gt;Vinted Scraper page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. You need a free Apify account.&lt;/li&gt;
&lt;li&gt;The easiest input is a URL. Set your filters on any Vinted site in the browser (brand, size, price, condition), copy the address bar and paste it into &lt;strong&gt;Vinted URLs&lt;/strong&gt;. Category, brand, single listing and seller wardrobe links work too.&lt;/li&gt;
&lt;li&gt;Or type keywords into &lt;strong&gt;Search queries&lt;/strong&gt;, one per line, and pick the &lt;strong&gt;Countries&lt;/strong&gt;. Each query runs in every selected country.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Max listings per search&lt;/strong&gt;. I used 25. &lt;code&gt;0&lt;/code&gt; means everything, and the actor splits the search into price ranges to get past Vinted's 960-result cap.&lt;/li&gt;
&lt;li&gt;Optional: tick &lt;strong&gt;Compare prices between countries&lt;/strong&gt; if you picked two or more countries.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;, then export the dataset as CSV, Excel or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4hgwlew7jv1jccmv0mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4hgwlew7jv1jccmv0mz.png" alt="Input form of the Vinted Scraper" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Main input options
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search queries&lt;/strong&gt; and &lt;strong&gt;Vinted URLs&lt;/strong&gt;: what to scrape. You can mix both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Countries&lt;/strong&gt; or &lt;strong&gt;All 26 countries&lt;/strong&gt;: which marketplaces to search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sort by&lt;/strong&gt;: &lt;code&gt;newest_first&lt;/code&gt; (default), &lt;code&gt;relevance&lt;/code&gt;, &lt;code&gt;price_low_to_high&lt;/code&gt;, &lt;code&gt;price_high_to_low&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Categories, Brands, Sizes, Condition, Colours, Material IDs, Min/Max price&lt;/strong&gt;: the same filters as on the website. Names or IDs both work; sizes behave best together with a category.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclude words in title&lt;/strong&gt; and &lt;strong&gt;Title must contain&lt;/strong&gt;: cleans up fuzzy search. Excluded listings are free. In my run, &lt;code&gt;titleMustInclude: ["501"]&lt;/code&gt; would have dropped the 8 off-model rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seller type&lt;/strong&gt;, &lt;strong&gt;Seller countries&lt;/strong&gt;, &lt;strong&gt;Min favourites&lt;/strong&gt;: filter by private vs business, seller location and demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listing details&lt;/strong&gt; and &lt;strong&gt;Seller profiles&lt;/strong&gt;: paid enrichment, described above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only new listings&lt;/strong&gt;, &lt;strong&gt;Also return price drops&lt;/strong&gt;, &lt;strong&gt;Also detect sold / removed listings&lt;/strong&gt;, &lt;strong&gt;Monitor name&lt;/strong&gt;: monitoring mode, covered below.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put your Apify API token in an environment variable called &lt;code&gt;APIFY_TOKEN&lt;/code&gt; (Console, Settings, API &amp;amp; Integrations). Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;levis 501&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;countries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxItemsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sortBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;newest_first&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compareCountries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/vinted-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;listings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;comparison&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recordType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country-comparison&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# price summary per marketplace
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalPriceEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# how many listings appear on both sites
&lt;/span&gt;&lt;span class="n"&gt;de_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;fr_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shared listings:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;de_ids&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;fr_ids&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# ten cheapest listings
&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalPriceEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalPriceEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;countries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medianPriceEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EUR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vinted_levis_501.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With my input this printed a median of 26.95 EUR for both marketplaces and 19 shared listings. Your numbers will differ because Vinted listings change every minute.&lt;/p&gt;

&lt;p&gt;Two small notes. The &lt;code&gt;condition&lt;/code&gt; column is localized ("Sehr gut" on vinted.de, "Très bon état" on vinted.fr), so map it to one language before you group by it. And filter on &lt;code&gt;recordType&lt;/code&gt; as shown, because the comparison row has a different shape from the listing rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling, monitoring and integrations
&lt;/h2&gt;

&lt;p&gt;The part I would use day to day is monitoring. Switch on &lt;strong&gt;Only new listings&lt;/strong&gt;, give the run a &lt;strong&gt;Monitor name&lt;/strong&gt;, and create a schedule in Apify Console (every 15 minutes or every hour). Each run then returns only listings it has not seen before. Every record gets a &lt;code&gt;listingStatus&lt;/code&gt; of &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;price-drop&lt;/code&gt;, &lt;code&gt;sold&lt;/code&gt; or &lt;code&gt;removed&lt;/code&gt;. Price drops include the previous price and the drop percentage. Sold and removed items include first seen date, last seen date and days on market, which is useful sell-through data if you resell.&lt;/p&gt;

&lt;p&gt;Already seen listings are not charged, so a monitor that finds 5 new items costs a fraction of a cent.&lt;/p&gt;

&lt;p&gt;From there you can push results to Google Sheets, Slack, Make, Zapier, n8n or a webhook through the Integrations tab. The actor can also be called from AI agents through the Apify MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing per 1,000 results
&lt;/h2&gt;

&lt;p&gt;Pay per event, proxies included. Current prices from the actor page:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free plan&lt;/th&gt;
&lt;th&gt;Starter&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Listing&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listing details (optional)&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seller profile (optional, once per seller)&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;td&gt;$0.60&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A country comparison row costs about $0.01 each. My test charged 50 listings plus 1 comparison row, which is roughly $0.11 on the Free plan. Listings removed by your title or seller filters are free, and you can set a maximum cost per run so it stops at your limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The actor reads public pages only. It does not log in and does not need cookies. Vinted listings belong to real people, most of them private sellers, so keep personal data out of your pipeline unless you have a clear legal basis under GDPR. For price research you rarely need anything beyond price, brand, size, condition and country. I left seller IDs and seller profiles out of the screenshots and the code above for that reason. Keep request volume sensible and read Vinted's terms before you build anything commercial on top of the data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vinted</category>
      <category>python</category>
      <category>webscraping</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>How to scrape OLX.pl car listings by make, year and mileage with Python</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Tue, 20 Oct 2026 07:29:19 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-olxpl-car-listings-by-make-year-and-mileage-with-python-46j2</link>
      <guid>https://dev.to/norbertso/how-to-scrape-olxpl-car-listings-by-make-year-and-mileage-with-python-46j2</guid>
      <description>&lt;p&gt;OLX.pl is where a large share of Poland's used cars get listed, by dealers and private owners alike. The site has good filters, but there is no export button, and comparing 200 listings by hand gets old fast. This guide uses the &lt;a href="https://apify.com/liveclaude/olx-motoryzacja-pl" rel="noopener noreferrer"&gt;OLX Car Scraper Poland&lt;/a&gt; on Apify to turn a filtered car search into a table you can open in Excel or load into pandas.&lt;/p&gt;

&lt;p&gt;My test search: Toyota Corolla, passenger cars, model year 2018 or newer, whole country, capped at 40 listings. Everything below comes from that dataset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F42d1di87qhiaxoh29a2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F42d1di87qhiaxoh29a2o.png" alt="OLX Toyota Corolla listings in a table" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get per listing
&lt;/h2&gt;

&lt;p&gt;The field names are in Polish because the actor targets the Polish market. Here is what they mean:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example from my run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Listing title and link&lt;/td&gt;
&lt;td&gt;Toyota Corolla 1.5 VVT-i 125KM Comfort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;marka&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Make, model&lt;/td&gt;
&lt;td&gt;Toyota, Corolla&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rocznik&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Model year&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;przebiegKm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mileage in km&lt;/td&gt;
&lt;td&gt;180000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;cena&lt;/code&gt;, &lt;code&gt;waluta&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Price, currency&lt;/td&gt;
&lt;td&gt;52500, PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paliwo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fuel (Benzyna = petrol, CNG i Hybryda = hybrid)&lt;/td&gt;
&lt;td&gt;Benzyna&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;skrzynia&lt;/code&gt;, &lt;code&gt;naped&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Gearbox, drive&lt;/td&gt;
&lt;td&gt;Manualna, Na przednie koła&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;pojemnoscCm3&lt;/code&gt;, &lt;code&gt;mocKm&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Engine size (cm³), power (hp)&lt;/td&gt;
&lt;td&gt;1490, 125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;typNadwozia&lt;/code&gt;, &lt;code&gt;kolor&lt;/code&gt;, &lt;code&gt;stan&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Body type, colour, damaged or not&lt;/td&gt;
&lt;td&gt;Sedan, Biały, Nieuszkodzony&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;krajPochodzenia&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Country of origin&lt;/td&gt;
&lt;td&gt;Polska&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;miasto&lt;/code&gt;, &lt;code&gt;wojewodztwo&lt;/code&gt;, &lt;code&gt;gpsLat&lt;/code&gt;, &lt;code&gt;gpsLon&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;City, region, coordinates&lt;/td&gt;
&lt;td&gt;Wieliczka, Małopolskie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sprzedawcaTyp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Seller type (Prywatny = private, Komis / Firma = dealer)&lt;/td&gt;
&lt;td&gt;Komis / Firma&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;dataDodania&lt;/code&gt;, &lt;code&gt;dataOdswiezenia&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Posted and refreshed timestamps&lt;/td&gt;
&lt;td&gt;2026-10-07T18:01:47+02:00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;glowneZdjecie&lt;/code&gt;, &lt;code&gt;zdjecia&lt;/code&gt;, &lt;code&gt;opis&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Main photo, all photos, description (HTML)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is also &lt;code&gt;sprzedawcaNazwa&lt;/code&gt;, the seller's display name. For private sellers that is a person's name, so treat it carefully (more on that at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  What 40 Corollas looked like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prices went from 36,900 PLN to 141,900 PLN, median 78,195 PLN. Median mileage was about 90,000 km.&lt;/li&gt;
&lt;li&gt;25 cars were hybrids, 11 petrol, 3 LPG and 1 diesel. All 25 hybrids were automatics, and every non-hybrid had a manual gearbox.&lt;/li&gt;
&lt;li&gt;34 listings came from dealers and 6 from private sellers.&lt;/li&gt;
&lt;li&gt;6 listings were brand new 2026 cars with 1 to 5 km on the clock, all from dealers. They pull the averages up, so filter them out if you want used-car prices.&lt;/li&gt;
&lt;li&gt;27 of the 40 cars were in the Mazowieckie region (Warsaw and around). I did not set a city, so that is just where the supply sits for this query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparing like with like is where a table beats scrolling. For model years 2018 to 2023 only, the 14 hybrids had a median price of 79,370 PLN against 58,450 PLN for the 10 petrol cars, at similar median mileage (about 120,000 vs 115,000 km). That is roughly a 21,000 PLN premium for the hybrid in this small sample. Forty rows won't settle a market question. It does show what you can answer in two minutes once the data is in a DataFrame.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/olx-motoryzacja-pl" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pick a &lt;strong&gt;Kategoria&lt;/strong&gt; (category): passenger cars, motorcycles, trucks, vans, trailers or parts.&lt;/li&gt;
&lt;li&gt;Choose one or more &lt;strong&gt;Marki&lt;/strong&gt; (makes). Multi-select works, so BMW and Audi can go in one run.&lt;/li&gt;
&lt;li&gt;Type &lt;strong&gt;Modele&lt;/strong&gt; (models) if you want them, for example &lt;code&gt;Golf, Passat&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set filters: price, year, mileage, fuel, gearbox, city with a radius.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Maks. liczba ogłoszeń&lt;/strong&gt; (max listings). I used 40. Click &lt;strong&gt;Start&lt;/strong&gt; and export from the Storage tab as CSV, Excel or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The form groups filters into sections, so you never have to build OLX URLs yourself:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5i3uecqwbsl3cxjvw24k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5i3uecqwbsl3cxjvw24k.png" alt="OLX Car Scraper input form" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grab your API token from Settings → API &amp;amp; Integrations in the Apify console and keep it in an environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kategoria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;samochody-osobowe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marki&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;toyota&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;modele&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Corolla&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rocznikOd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2018&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxLiczbaOgloszen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/olx-motoryzacja-pl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Leave out new cars and the seller name column
&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;przebiegKm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sprzedawcaNazwa&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rocznik&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paliwo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cena&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="n"&gt;median_price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cena&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="n"&gt;median_km&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;przebiegKm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rocznik&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;przebiegKm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cena&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paliwo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skrzynia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mocKm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;miasto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sprzedawcaTyp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cena&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;olx_corolla.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;call()&lt;/code&gt; waits for the run to end. For runs with thousands of listings, &lt;code&gt;start()&lt;/code&gt; plus a webhook is cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input options worth knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Category and makes.&lt;/strong&gt; &lt;code&gt;kategoria&lt;/code&gt; takes &lt;code&gt;samochody-osobowe&lt;/code&gt;, &lt;code&gt;motocykle&lt;/code&gt;, &lt;code&gt;ciezarowe&lt;/code&gt;, &lt;code&gt;dostawcze&lt;/code&gt;, &lt;code&gt;przyczepy-naczepy&lt;/code&gt; or &lt;code&gt;czesci&lt;/code&gt;. &lt;code&gt;marki&lt;/code&gt; is a list of lowercase slugs like &lt;code&gt;bmw&lt;/code&gt; or &lt;code&gt;volkswagen&lt;/code&gt;, and &lt;code&gt;modele&lt;/code&gt; is free text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ranges.&lt;/strong&gt; &lt;code&gt;cenaOd&lt;/code&gt;/&lt;code&gt;cenaDo&lt;/code&gt; (price in PLN), &lt;code&gt;rocznikOd&lt;/code&gt;/&lt;code&gt;rocznikDo&lt;/code&gt; (year), &lt;code&gt;przebiegOd&lt;/code&gt;/&lt;code&gt;przebiegDo&lt;/code&gt; (km), &lt;code&gt;pojemnoscOd&lt;/code&gt;/&lt;code&gt;pojemnoscDo&lt;/code&gt; (cm³), &lt;code&gt;mocOd&lt;/code&gt;/&lt;code&gt;mocDo&lt;/code&gt; (hp).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specs.&lt;/strong&gt; &lt;code&gt;paliwa&lt;/code&gt; (fuel list), &lt;code&gt;skrzynia&lt;/code&gt; (&lt;code&gt;manual&lt;/code&gt; or &lt;code&gt;automatic&lt;/code&gt;), &lt;code&gt;naped&lt;/code&gt; (front, rear or one of the AWD variants), &lt;code&gt;typNadwozia&lt;/code&gt;, &lt;code&gt;kolor&lt;/code&gt;, and &lt;code&gt;stan&lt;/code&gt; to keep or drop damaged cars.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Location.&lt;/strong&gt; &lt;code&gt;miasto&lt;/code&gt; plus &lt;code&gt;promienKm&lt;/code&gt; (0 to 100 km) for a radius search around a city.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seller and freshness.&lt;/strong&gt; &lt;code&gt;typSprzedawcy&lt;/code&gt; filters to &lt;code&gt;private&lt;/code&gt; or &lt;code&gt;business&lt;/code&gt;. &lt;code&gt;opublikowaneW&lt;/code&gt; limits to listings from the last 24 hours, 7 days or 30 days. &lt;code&gt;tylkoZeZdjeciem&lt;/code&gt; keeps only listings with photos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Volume.&lt;/strong&gt; &lt;code&gt;maxLiczbaOgloszen&lt;/code&gt; defaults to 500 per run. &lt;code&gt;uzyjProxy&lt;/code&gt; turns on Apify proxy rotation if you run large jobs. &lt;code&gt;advancedUrls&lt;/code&gt; accepts raw OLX search URLs when a filter is missing from the form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling: alerts for new listings
&lt;/h2&gt;

&lt;p&gt;The most practical feature is &lt;code&gt;monitorNowe&lt;/code&gt;. With it on, each run returns only listings that were not there last time. &lt;code&gt;wykrywajZmianyCen&lt;/code&gt; (on by default) also flags price drops on cars you already saw. Here is an input a dealer could schedule every 30 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kategoria"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"samochody-osobowe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"marki"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bmw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"audi"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cenaDo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rocznikOd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"przebiegDo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"miasto"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warszawa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"promienKm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monitorNowe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the schedule in the Apify console, then send results to Google Sheets, Slack, Make, Zapier or n8n, or to your own endpoint with a webhook. You can also call the actor from Claude, ChatGPT or Cursor through the &lt;a href="https://mcp.apify.com" rel="noopener noreferrer"&gt;Apify MCP server&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Pay per event. Per 1,000 events at the current price list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Bronze&lt;/th&gt;
&lt;th&gt;Silver&lt;/th&gt;
&lt;th&gt;Gold&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Listing scraped&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$4&lt;/td&gt;
&lt;td&gt;$3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New listing found (monitoring)&lt;/td&gt;
&lt;td&gt;$12&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;$8&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price change detected&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$4&lt;/td&gt;
&lt;td&gt;$3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each run also has a $0.05 start fee. New users get their first 100 listings free, which covers a test like mine twice over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The actor reads public OLX listings. Private sellers are people, and their names and anything in a free-text description can be personal data under GDPR. Drop &lt;code&gt;sprzedawcaNazwa&lt;/code&gt; unless you have a lawful reason to keep it, do not build contact lists from private listings, and check that your use fits OLX.pl's terms. Keep run frequency sensible: every 30 minutes for a narrow search is plenty.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>cars</category>
      <category>dataanalysis</category>
    </item>
    <item>
      <title>How to scrape Allegro.pl offers, sellers and prices with Python and pandas</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Tue, 20 Oct 2026 07:29:01 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-allegropl-offers-sellers-and-prices-with-python-and-pandas-91p</link>
      <guid>https://dev.to/norbertso/how-to-scrape-allegropl-offers-sellers-and-prices-with-python-and-pandas-91p</guid>
      <description>&lt;p&gt;Allegro is the biggest marketplace in Poland, and if you sell there (or compete with people who do) you end up checking prices by hand far too often. This guide shows how to pull Allegro search results into a spreadsheet or a pandas DataFrame with the &lt;a href="https://apify.com/liveclaude/allegro-seller-scraper" rel="noopener noreferrer"&gt;Allegro Product Scraper&lt;/a&gt; on Apify. No login, no browser automation on your side.&lt;/p&gt;

&lt;p&gt;For this post I ran it on one search phrase, &lt;code&gt;ekspres do kawy&lt;/code&gt; (coffee machine), sorted by popularity, new items only, capped at 40 offers. The run finished in about 75 seconds. Every number below comes from that dataset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fthbqvkoo68ch06b1tv7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fthbqvkoo68ch06b1tv7u.png" alt="Allegro search results for " width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get per offer
&lt;/h2&gt;

&lt;p&gt;The default mode reads the search listing only, which is fast and cheap. One row per offer:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;th&gt;Example from my run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Offer title&lt;/td&gt;
&lt;td&gt;Ekspres ciśnieniowy automatyczny Philips ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;price&lt;/code&gt; / &lt;code&gt;currency&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Current price&lt;/td&gt;
&lt;td&gt;943.00 PLN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;originalPrice&lt;/code&gt;, &lt;code&gt;discountPercent&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Price before discount (lowest of last 30 days), if shown&lt;/td&gt;
&lt;td&gt;249.00 → 199.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;priceWithDelivery&lt;/code&gt;, &lt;code&gt;deliveryTime&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Cheapest price incl. shipping and the delivery promise&lt;/td&gt;
&lt;td&gt;957.99, "dostawa jutro"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;smart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allegro Smart! free delivery eligible&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lowestPriceGuarantee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"Gwarancja najniższej ceny" badge&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;promoted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sponsored placement&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recentBuyers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"X people bought recently" counter&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;superSeller&lt;/code&gt;, &lt;code&gt;sellerRating&lt;/code&gt;, &lt;code&gt;sellerIsCompany&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Seller badges and rating&lt;/td&gt;
&lt;td&gt;true, 99.5, true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;productOffersCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;How many sellers offer the same catalogue product&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;productRating&lt;/code&gt;, &lt;code&gt;productReviewsCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Product reviews&lt;/td&gt;
&lt;td&gt;4.95, 544&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;parameters&lt;/code&gt;, &lt;code&gt;mainImage&lt;/code&gt;, &lt;code&gt;images&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Key specs and photos&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Switch on &lt;strong&gt;Full offer details&lt;/strong&gt; (&lt;code&gt;scrapeDetails: true&lt;/code&gt;) and the scraper also opens each offer page. Then you get EAN/GTIN, brand, stock, units sold in the last 30 days, the full parameter table, description, warranty, category path and the rating distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 40 offers told me
&lt;/h2&gt;

&lt;p&gt;A quick look at the raw data before any cleaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prices ranged from 17.99 PLN to 1,949 PLN, median 232.76 PLN. That median is low because a popularity sort mixes in accessories. 11 of the 40 rows were mats, gaskets, descaler or toy coffee machines for kids. Filtering titles down to real machines left 29 rows with a median of 419 PLN.&lt;/li&gt;
&lt;li&gt;36 of 40 offers were promoted. On a popularity-sorted first page, sponsored slots are most of what you see. If you want organic results, set &lt;code&gt;includePromoted&lt;/code&gt; to false.&lt;/li&gt;
&lt;li&gt;38 offers were Smart! and only 7 had free delivery for everyone. &lt;code&gt;priceWithDelivery&lt;/code&gt; is the column to compare if your customers do not have Smart!.&lt;/li&gt;
&lt;li&gt;18 offers carried the Lowest Price Guarantee badge, all of them actual machines.&lt;/li&gt;
&lt;li&gt;The median machine had 22 competing sellers for the same catalogue product (&lt;code&gt;productOffersCount&lt;/code&gt;). One cheap automatic machine had 320.&lt;/li&gt;
&lt;li&gt;Seller ratings sat between 94.8% and 100%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point about competing sellers is where the scraper gets useful for pricing work. If a product has 50 sellers, you probably want all 50 prices, which is what the EAN mode below is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: no code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/liveclaude/allegro-seller-scraper" rel="noopener noreferrer"&gt;actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. A free Apify account works.&lt;/li&gt;
&lt;li&gt;Pick the marketplace: Allegro.pl, .cz or .sk. Currency follows (PLN, CZK, EUR).&lt;/li&gt;
&lt;li&gt;Add one or more &lt;strong&gt;Search phrases&lt;/strong&gt;. You can also paste &lt;strong&gt;Allegro URLs&lt;/strong&gt;: a category, a seller shop (&lt;code&gt;/uzytkownik/...&lt;/code&gt;), single offers or product pages. Or paste &lt;strong&gt;EAN codes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Max. offers per input&lt;/strong&gt;. I used 40.&lt;/li&gt;
&lt;li&gt;Optional filters: min/max price, condition, sort order, Smart! only, hide promoted.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;, wait, then export from the Storage tab to Excel, CSV or JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the input form so you can see where everything sits:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmp0colpd33gjnipmt8zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmp0colpd33gjnipmt8zq.png" alt="Allegro Product Scraper input form" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python with apify-client and pandas
&lt;/h2&gt;

&lt;p&gt;Install the two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the actor and load the results. Your API token is under Settings → API &amp;amp; Integrations in the Apify console. Keep it in an environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;run_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;marketplace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ekspres do kawy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxItemsPerInput&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sortOrder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;popularity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/allegro-seller-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;list_items&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Drop accessories that a popularity sort pulls in
&lt;/span&gt;&lt;span class="n"&gt;junk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mata|uszczel|odkamien|podkładk|dla dzieci|zabawka&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;machines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;junk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priceWithDelivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;promoted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recentBuyers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;productOffersCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lowestPriceGuarantee&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;machines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recentBuyers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median price:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;machines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;machines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allegro_coffee_machines.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;call()&lt;/code&gt; method blocks until the run ends, so for big jobs you may prefer &lt;code&gt;start()&lt;/code&gt; and polling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The input options that matter
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ways in.&lt;/strong&gt; &lt;code&gt;searchQueries&lt;/code&gt;, &lt;code&gt;startUrls&lt;/code&gt; and &lt;code&gt;eans&lt;/code&gt; can all go into one run. Category URLs are good for whole-segment exports. A seller shop URL gives you a competitor's full catalogue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EAN mode.&lt;/strong&gt; Put barcodes in &lt;code&gt;eans&lt;/code&gt; and the actor returns every seller of that product, ranked by price, with lowest, highest and average price. &lt;code&gt;maxOffersPerProduct&lt;/code&gt; (default 50) caps sellers per product. &lt;code&gt;allSellersForProducts&lt;/code&gt; does the same for product URLs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"eans"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"195949036842"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5702017584072"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxOffersPerProduct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output shape.&lt;/strong&gt; &lt;code&gt;outputFormat: "offers"&lt;/code&gt; gives one row per offer. &lt;code&gt;"products"&lt;/code&gt; groups them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More than 6,000 results.&lt;/strong&gt; Allegro stops at 100 pages per search. With &lt;code&gt;deepPagination&lt;/code&gt; on (the default), the actor splits large searches into price bands so a full category export still works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hidden discounts.&lt;/strong&gt; &lt;code&gt;detectHiddenDiscounts&lt;/code&gt; shows, for Lowest Price Guarantee offers, the price the seller set and how much Allegro covers (&lt;code&gt;realSellerPrice&lt;/code&gt;, &lt;code&gt;hiddenDiscount&lt;/code&gt;). No extra charge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seller company data.&lt;/strong&gt; &lt;code&gt;sellerCompanyDetails&lt;/code&gt; adds company name, NIP, KRS and address from the seller's public business info.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Images.&lt;/strong&gt; &lt;code&gt;downloadImages&lt;/code&gt; with &lt;code&gt;maxImages&lt;/code&gt; (default 5) stores the files, handy if you are building a product feed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling and integrations
&lt;/h2&gt;

&lt;p&gt;For price monitoring, turn on &lt;code&gt;onlyChanges&lt;/code&gt; and give the job a &lt;code&gt;monitorId&lt;/code&gt;, for example &lt;code&gt;"coffee-machines"&lt;/code&gt;. Each scheduled run then returns only new offers and changed prices, with &lt;code&gt;previousPrice&lt;/code&gt; and &lt;code&gt;priceChange&lt;/code&gt; fields. Unchanged offers are not charged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"startUrls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://allegro.pl/kategoria/smartfony-i-telefony-komorkowe-165"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"onlyChanges"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monitorId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"smartphones"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxItemsPerInput"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a schedule in the Apify console (daily at 6:00 is a sane start). Results can flow into Google Sheets, Make, Zapier, n8n or Slack, or a webhook can ping your own service when a run finishes. The actor also works from Claude, ChatGPT or Cursor through the &lt;a href="https://mcp.apify.com" rel="noopener noreferrer"&gt;Apify MCP server&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Pay per event, platform usage included. Per 1,000 offers, at the current price list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Starter&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Offer from listing&lt;/td&gt;
&lt;td&gt;$3.50&lt;/td&gt;
&lt;td&gt;$3.20&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$2.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offer with full details&lt;/td&gt;
&lt;td&gt;$6.00&lt;/td&gt;
&lt;td&gt;$5.50&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$4.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Monitoring, hidden-discount detection and image download cost nothing extra. At the Free tier rate, my test run (36 charged listing events) works out to about 13 cents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;The actor reads public offer pages only. Business sellers' company data is information they publish on Allegro themselves. Some Allegro sellers are private persons, though, and their logins can be personal data under GDPR. If you store or share the dataset, drop or pseudonymise &lt;code&gt;sellerLogin&lt;/code&gt; for non-company sellers (&lt;code&gt;sellerIsCompany&lt;/code&gt; tells you which). Keep request volumes reasonable and check Allegro's terms for your use case.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>allegro</category>
      <category>webscraping</category>
      <category>python</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>How to scrape Glassdoor jobs and salaries into Excel or Python (no login, no API key)</title>
      <dc:creator>Norbert Sobala</dc:creator>
      <pubDate>Mon, 19 Oct 2026 21:31:36 +0000</pubDate>
      <link>https://dev.to/norbertso/how-to-scrape-glassdoor-jobs-and-salaries-into-excel-or-python-no-login-no-api-key-5352</link>
      <guid>https://dev.to/norbertso/how-to-scrape-glassdoor-jobs-and-salaries-into-excel-or-python-no-login-no-api-key-5352</guid>
      <description>&lt;p&gt;Glassdoor is one of the few job boards that shows a &lt;strong&gt;salary range next to the job&lt;/strong&gt;: either the employer's own or a Glassdoor estimate. It also shows the &lt;strong&gt;company rating&lt;/strong&gt;. That makes the data useful beyond job hunting. Two common uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Salary benchmarking.&lt;/strong&gt; What do product managers in Berlin actually get offered?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sales and recruiting.&lt;/strong&gt; Which companies are hiring right now, and for which roles? A company opening five sales positions this month is usually a company with budget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Glassdoor has no public API for this, and logged-out visitors only see the first page of results. This guide uses a ready-made scraper on Apify that handles both problems. You can get the data without writing any code, or call it from Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;p&gt;Every job comes back as one clean record:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Product Manager (m/w/d)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;company&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lokalleads GmbH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;location&lt;/code&gt; / &lt;code&gt;country&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Berlin, Germany&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;salaryMin&lt;/code&gt; / &lt;code&gt;salaryMax&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;60000 / 60000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;salaryCurrency&lt;/code&gt; / &lt;code&gt;salaryPeriod&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;EUR / year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;salaryIsEstimate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;false (set by the employer, not a Glassdoor estimate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;salaryYearlyMinEur&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;60000 (normalised to EUR per year, so you can compare countries)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remote&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;hybrid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;easyApply&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;postedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-14&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can also turn on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full descriptions&lt;/strong&gt;, which add the whole job text, employment type and industry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Company signals&lt;/strong&gt;, which add one summary record per company: open roles, jobs posted in the last 7 days, remote share and median salary. This is handy for spotting companies that are scaling up.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 1: no code (2 minutes)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://apify.com/liveclaude/glassdoor-jobs-scraper" rel="noopener noreferrer"&gt;Glassdoor Jobs Scraper&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Type your search, e.g. &lt;code&gt;product manager&lt;/code&gt;, choose a location (&lt;code&gt;Berlin&lt;/code&gt;) and a country.&lt;/li&gt;
&lt;li&gt;Optionally tick &lt;em&gt;Only jobs with salary&lt;/em&gt;, &lt;em&gt;Remote only&lt;/em&gt;, or a date range such as &lt;em&gt;Posted in the last 7 days&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;. When the run finishes, export to &lt;strong&gt;Excel, CSV or JSON&lt;/strong&gt;, or send the data straight to Google Sheets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fialyt2830ws5c7ghf2dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fialyt2830ws5c7ghf2dp.png" alt="Glassdoor Jobs Scraper input form" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we ran &lt;em&gt;"product manager" in Berlin&lt;/em&gt;, 10 jobs came back in under a minute. Two of them had a salary published by the employer: €60,000 and €72,000 a year. The employers ranged from small agencies to Bundesdruckerei and Berliner Sparkasse. How many listings carry a salary depends on the country. Several US states require pay ranges in job ads, so US searches usually return far more numbers than German ones. If you only want listings with pay, tick &lt;em&gt;Only jobs with salary&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2ifgefwoo06k89lhlaji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2ifgefwoo06k89lhlaji.png" alt="Results of a Glassdoor search for product manager jobs in Berlin" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;apify-client pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_APIFY_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Console → Settings → API &amp;amp; Integrations
&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liveclaude/glassdoor-jobs-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data analyst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data engineer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;locations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postedWithin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;week&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onlyWithSalary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxJobsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# median advertised salary per search, in EUR per year
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQuery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryYearlyMinEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryYearlyMaxEur&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;glassdoor_jobs.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;salaryYearlyMinEur&lt;/code&gt; and &lt;code&gt;salaryYearlyMaxEur&lt;/code&gt; fields are already converted to euros per year. That lets you compare London with Sydney or New York without converting anything yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it fresh automatically
&lt;/h2&gt;

&lt;p&gt;Add a &lt;strong&gt;Schedule&lt;/strong&gt; in Apify, for example every Monday at 8:00, and turn on &lt;em&gt;Only new jobs&lt;/em&gt;. Each run then returns only listings you haven't seen before. From there you can push new jobs to Slack or email as alerts, or append them to a Google Sheet and keep a running salary tracker. Make, Zapier and n8n work too if you want the data in a CRM.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it cost?
&lt;/h2&gt;

&lt;p&gt;You pay per result: &lt;strong&gt;$0.50 per 1,000 jobs&lt;/strong&gt;, and &lt;strong&gt;$3 per 1,000&lt;/strong&gt; if you also want full descriptions. Platform costs are included. A weekly tracker of a few hundred jobs costs cents. Apify's free plan includes monthly credit, which is enough to try it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on responsible use
&lt;/h2&gt;

&lt;p&gt;The scraper collects only what Glassdoor shows publicly to logged-out visitors. It does not log in and does not collect reviews written by individuals. If you store data about people (for example, recruiters' names in descriptions), treat it according to GDPR or your local law.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions or a missing field? Open an issue on the &lt;a href="https://apify.com/liveclaude/glassdoor-jobs-scraper" rel="noopener noreferrer"&gt;Actor page&lt;/a&gt;. Requests usually ship within a few days.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>datascience</category>
      <category>career</category>
    </item>
  </channel>
</rss>
