<?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: CleanScrape</title>
    <description>The latest articles on DEV Community by CleanScrape (@cleanscrape).</description>
    <link>https://dev.to/cleanscrape</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%2F4126565%2F7f3a2bef-43ea-47db-a8a6-f8923b4ae916.png</url>
      <title>DEV Community: CleanScrape</title>
      <link>https://dev.to/cleanscrape</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cleanscrape"/>
    <language>en</language>
    <item>
      <title>A week of Nvidia news, past the 100-article limit</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Mon, 05 Oct 2026 16:05:12 +0000</pubDate>
      <link>https://dev.to/cleanscrape/a-week-of-nvidia-news-past-the-100-article-limit-jch</link>
      <guid>https://dev.to/cleanscrape/a-week-of-nvidia-news-past-the-100-article-limit-jch</guid>
      <description>&lt;p&gt;A Google News search stops at about 100 articles. That's fine for a quick look, but not if you want everything the press wrote about a company in one week. A big name like Nvidia gets more than 100 articles in a single day, so a week-long search quietly leaves most of them out.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://apify.com/cleanscrape/google-news-scraper" rel="noopener noreferrer"&gt;CleanScrape's Google News Scraper API&lt;/a&gt; partly for this. I'm the developer, so this is a walkthrough of my own tool, not an independent review. An AI agent wrote this walkthrough from my run, and every number in it was checked against that run.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/fVFARgjpNZo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  One search per day
&lt;/h2&gt;

&lt;p&gt;The fix is simple: instead of one search for the whole week, run one search for each day and combine the results. The Actor does that when you turn on &lt;strong&gt;Search each day separately&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the example I typed &lt;code&gt;Nvidia&lt;/code&gt;, picked September 21 to 27, 2026, and set &lt;strong&gt;Maximum articles&lt;/strong&gt; to 300. You don't need a Google account or an API key. You do need an Apify account to run the Actor. The same input as JSON:&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;"queries"&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;"Nvidia"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"edition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US:en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"startDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-21"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"endDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"splitByDay"&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;"maxArticles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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;That run returned 276 articles instead of about 100, each with the headline, the publisher, the publish time and a link.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the week looked like
&lt;/h2&gt;

&lt;p&gt;Counted by publish day (in UTC), Friday was the busiest, with 64 articles. By publisher, Yahoo Finance alone ran 73 of the 276.&lt;/p&gt;

&lt;p&gt;One honest caveat: each day's search also returned Google's maximum of 100 entries, so the run report marks those days as possibly incomplete. More articles may exist. Splitting by day gets you much closer to the full picture, but for a name this busy it isn't a guarantee of every article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publisher links
&lt;/h2&gt;

&lt;p&gt;Google News links point back to Google, not to the article. Where it can, the Actor turns them into the publisher's own link, and a &lt;strong&gt;link status&lt;/strong&gt; column tells you which ones it found. In this run, 85 links were turned into the publisher's page and 191 kept the Google News link, because Google limits how many links can be looked up in a row. The Google link still opens the article; it just takes one extra hop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the topic after the first run
&lt;/h2&gt;

&lt;p&gt;To keep up with a topic without getting the same headlines again, turn on &lt;strong&gt;Only articles not saved before&lt;/strong&gt; and give it a &lt;strong&gt;Watch name&lt;/strong&gt;. Later runs with the same watch name return only articles that weren't delivered before. Save the input as a task and schedule it daily or weekly.&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;"queries"&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;"Nvidia"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"newOnly"&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;"watchName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nvidia news"&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;I wrote more about that setup in &lt;a href="https://dev.to/cleanscrape/a-small-news-watchlist-that-doesnt-send-the-same-headlines-every-day-71"&gt;a small news watchlist that doesn't send the same headlines every day&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Export and cost
&lt;/h2&gt;

&lt;p&gt;Export the &lt;strong&gt;Articles&lt;/strong&gt; view as CSV or Excel. The run report shows what every search returned, including which days hit Google's limit.&lt;/p&gt;

&lt;p&gt;The price is $0.95 per 1,000 saved articles, with no start fee and platform usage included. The 276 articles above cost about $0.26 at base prices. Check the Pricing tab for your account's rate, and set a spending limit before larger runs.&lt;/p&gt;

&lt;p&gt;Questions or a reproducible problem: use the Actor's Issues tab or email &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;. CleanScrape is independent of Google and Apify, and Nvidia is used here as a public-news example, not an endorsement.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>pytrends keeps failing with 429 errors? Here's a one-line fix</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 04 Oct 2026 14:04:04 +0000</pubDate>
      <link>https://dev.to/cleanscrape/pytrends-keeps-failing-with-429-errors-heres-a-one-line-fix-4g00</link>
      <guid>https://dev.to/cleanscrape/pytrends-keeps-failing-with-429-errors-heres-a-one-line-fix-4g00</guid>
      <description>&lt;p&gt;If you have a Python script that pulls Google Trends data with pytrends, there's a good chance it stopped working. pytrends was archived in April 2025, and most requests now end in &lt;code&gt;429 Too Many Requests&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/CleanScrape/trendreq" rel="noopener noreferrer"&gt;trendreq&lt;/a&gt; to fix that without rewriting anything. It has the same &lt;code&gt;TrendReq&lt;/code&gt; class and returns the same DataFrames, but the requests run on my &lt;a href="https://apify.com/cleanscrape/google-trends-scraper" rel="noopener noreferrer"&gt;Google Trends Actor&lt;/a&gt; on Apify, where the proxies and retries are handled for you. I'm the developer, so this is a walkthrough of my own tool, not an independent review. An AI agent wrote it from a real run, and the output below is from that run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why pytrends gets 429s
&lt;/h2&gt;

&lt;p&gt;Google Trends has no official public API (Google's own is still a closed alpha). pytrends talks to the same internal endpoints the website uses: one request for a short-lived token, then one per chart. Every request comes from your IP address, and Google limits how often one address can do that. A loop over a few dozen keywords is usually enough to get blocked for a while.&lt;/p&gt;

&lt;p&gt;The usual advice is sleeping between calls, rotating proxies yourself, or patching the library. That works for a bit, then it doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The change
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# from pytrends.request import TrendReq
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;trendreq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TrendReq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install it and set your Apify token (a free Apify account includes $5 of usage a month):&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;trendreq
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;APIFY_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything else stays the same:&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;pytrends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TrendReq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en-US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pytrends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build_payload&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iced coffee&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;cold brew&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;today 12-m&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;geo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;over_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytrends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interest_over_time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;by_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytrends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interest_by_region&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inc_geo_code&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;related&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytrends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;related_queries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What came back
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;interest_over_time()&lt;/code&gt;, the last few weeks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            iced coffee  cold brew  isPartial
date
2026-09-06           57         63      False
2026-09-13           59         68      False
2026-09-20           47         51      False
2026-09-27           42         49      False
2026-10-04           32         33       True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;interest_by_region()&lt;/code&gt;, sorted by cold brew. Oregon and Washington lean hardest toward cold brew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           geoCode  iced coffee  cold brew
geoName
Oregon       US-OR           31         69
Washington   US-WA           35         65
Kansas       US-KS           35         65
Montana      US-MT           36         64
California   US-CA           37         63
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the rising related queries for cold brew, which is where product ideas tend to show up:&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="w"&gt;                                 &lt;/span&gt;&lt;span class="err"&gt;query&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;toasted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;coconut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;brew&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;19700&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="err"&gt;smores&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;brew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;starbucks&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;19700&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;how&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;brew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;concentrate&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;2050&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole thing took one run of about 9 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  One run instead of three
&lt;/h2&gt;

&lt;p&gt;Each method call starts one Apify run, and each run has a small start fee. If you want several data types for the same keywords, ask for them together:&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;pytrends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interest_over_time&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;related_queries&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;interest_by_region&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;After that, the three methods read from the same run. The example above did exactly that: 102 rows, about $0.36 at the base price.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's different from pytrends
&lt;/h2&gt;

&lt;p&gt;Most of it works the same, but not all of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Related topics come back empty.&lt;/strong&gt; Google currently returns an empty list for automated requests (pytrends gets the same), so &lt;code&gt;related_topics()&lt;/code&gt; gives &lt;code&gt;None&lt;/code&gt; with a warning. Related queries work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;City results get coordinates.&lt;/strong&gt; &lt;code&gt;interest_by_region(resolution="CITY")&lt;/code&gt; adds latitude and longitude, because the US has several Springfields and they shouldn't merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;US metro areas work&lt;/strong&gt; with &lt;code&gt;resolution="DMA"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gprop&lt;/code&gt; isn't supported yet&lt;/strong&gt;, so YouTube, News and Shopping search raise a clear error instead of returning web data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;suggestions()&lt;/code&gt; and &lt;code&gt;categories()&lt;/code&gt; aren't there yet.&lt;/strong&gt; They raise &lt;code&gt;NotImplementedError&lt;/code&gt; with a short explanation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trending searches&lt;/strong&gt; (&lt;code&gt;trending_searches&lt;/code&gt;, &lt;code&gt;today_searches&lt;/code&gt;) work, and &lt;code&gt;trending_now("US")&lt;/code&gt; adds approximate traffic and related news headlines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exception names are the same, so &lt;code&gt;except ResponseError:&lt;/code&gt; blocks keep working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;You pay Apify for the Actor's rows: $0.05 per run plus $0.003 per row at the base price, less on paid plans. Two keywords over 12 months is about $0.37. Today's trending searches for one country is about $0.08. The free monthly credit covers a few dozen typical calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code, docs and offline tests: &lt;a href="https://github.com/CleanScrape/trendreq" rel="noopener noreferrer"&gt;github.com/CleanScrape/trendreq&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Actor it runs on: &lt;a href="https://apify.com/cleanscrape/google-trends-scraper" rel="noopener noreferrer"&gt;apify.com/cleanscrape/google-trends-scraper&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If something you rely on in pytrends doesn't work, open an issue on GitHub. I'd rather hear about it and fix it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>seo</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>How Sinner won Wimbledon 2025, in break points</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sat, 03 Oct 2026 20:01:09 +0000</pubDate>
      <link>https://dev.to/cleanscrape/how-sinner-won-wimbledon-2025-in-break-points-3jjc</link>
      <guid>https://dev.to/cleanscrape/how-sinner-won-wimbledon-2025-in-break-points-3jjc</guid>
      <description>&lt;p&gt;The scoreline of the 2025 Wimbledon men's final says Jannik Sinner beat Carlos Alcaraz 4-6 6-4 6-4 6-4. It doesn't say how. For that you need the match statistics, and for a whole tournament you need them in one table, with the counts behind every percentage.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://apify.com/cleanscrape/tennis-match-data" rel="noopener noreferrer"&gt;CleanScrape's Tennis Scraper API&lt;/a&gt; to get that table from Flashscore. I'm the developer, so this is a walkthrough of my own tool, not an independent review. An AI agent wrote this walkthrough from my run, and every number in it was checked against that run.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/eDn2dKHsRXA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  One line of input
&lt;/h2&gt;

&lt;p&gt;Open the Actor and type &lt;code&gt;Wimbledon 2025&lt;/code&gt; into &lt;strong&gt;Tournaments, players or matches&lt;/strong&gt;. Set &lt;strong&gt;Maximum matches&lt;/strong&gt; to 500 and start.&lt;/p&gt;

&lt;p&gt;You don't need a Flashscore account, cookies or an API key. You do need an Apify account to run the Actor. The same input as JSON:&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;"targets"&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;"Wimbledon 2025"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&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;The list takes other things too: a player (&lt;code&gt;Sinner 2026&lt;/code&gt;), a draw (&lt;code&gt;US Open women 2024&lt;/code&gt;), a common name (&lt;code&gt;Roland Garros 2024&lt;/code&gt;) or any Flashscore link. The run report says how each line was read. Mine said: &lt;em&gt;"Wimbledon 2025" was read as ATP Wimbledon 2025, WTA Wimbledon 2025.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What came back
&lt;/h2&gt;

&lt;p&gt;478 singles matches, men's and women's, qualifying included. Each row has the round, the score with tiebreak points (&lt;code&gt;7-6(2) 6-4 6-4&lt;/code&gt;), the status (&lt;code&gt;finished&lt;/code&gt;, &lt;code&gt;retired&lt;/code&gt; and so on), the match time, the umpire and the match statistics. All 478 had full statistics. The run took about nine minutes.&lt;/p&gt;

&lt;p&gt;The statistics keep their counts. You don't just get "first serve points won: 75%", you get &lt;code&gt;firstServePointsWonHome&lt;/code&gt; = 54 and &lt;code&gt;firstServePointsPlayedHome&lt;/code&gt; = 72. That matters as soon as you add matches together, because you can't average percentages from matches of different lengths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding it up
&lt;/h2&gt;

&lt;p&gt;I took the men's main draw and summed each finalist's serve numbers over their seven matches:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Service games held&lt;/th&gt;
&lt;th&gt;Break points faced&lt;/th&gt;
&lt;th&gt;Break points saved&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sinner&lt;/td&gt;
&lt;td&gt;93 of 99&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alcaraz&lt;/td&gt;
&lt;td&gt;118 of 133&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sinner faced fewer than half as many break points as Alcaraz over the fortnight. In the final itself he saved 4 of 6.&lt;/p&gt;

&lt;p&gt;Two caveats. Sinner's fourth-round match against Grigor Dimitrov ended in retirement with Dimitrov two sets up, so it counts with the statistics of the part that was played. And seven matches against different opponents isn't a controlled comparison. It's a description of how the two got through the draw, not a ranking of servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Point-by-point, form and head-to-head
&lt;/h2&gt;

&lt;p&gt;Two switches add more. &lt;strong&gt;Point-by-point&lt;/strong&gt; gives every game: who served, who won, whether serve was broken, and every point score with break points, set points and match points marked. The last game of the final went 15-0, 30-0, 40-0, 40-15, with match point flagged on the last two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Form and head-to-head&lt;/strong&gt; adds each player's latest matches, overall and on the surface, and their earlier meetings. It's meant for matches coming up. For a past match, the form lists are what Flashscore shows today, so they can include later matches. The row says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Export and check the report
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Export&lt;/strong&gt;, pick the &lt;strong&gt;Statistics&lt;/strong&gt; view and download CSV or Excel. Use JSON when you want the nested data: per-set statistics, point-by-point and the form lists. Keep ID columns as text.&lt;/p&gt;

&lt;p&gt;The run report shows how each line was read, how many matches it listed, matched and saved, how many had full, basic or no statistics, and why the run stopped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it on what you actually care about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One tournament, several years:&lt;/strong&gt; &lt;code&gt;Wimbledon&lt;/code&gt;, with &lt;strong&gt;Editions per tournament&lt;/strong&gt; at 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A player's season:&lt;/strong&gt; &lt;code&gt;Swiatek 2025&lt;/code&gt;, with point-by-point if you want it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yesterday's results:&lt;/strong&gt; leave the list empty and pick &lt;strong&gt;Yesterday&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upcoming matches:&lt;/strong&gt; leave the list empty, pick &lt;strong&gt;Next 3 days&lt;/strong&gt;, status &lt;strong&gt;Scheduled&lt;/strong&gt;, and turn on form and head-to-head.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are ready-made examples for &lt;a href="https://apify.com/cleanscrape/tennis-match-data/examples/tennis-wimbledon-2025-statistics" rel="noopener noreferrer"&gt;Wimbledon 2025 with statistics&lt;/a&gt;, &lt;a href="https://apify.com/cleanscrape/tennis-match-data/examples/tennis-yesterday-atp-wta-results" rel="noopener noreferrer"&gt;yesterday's results&lt;/a&gt;, &lt;a href="https://apify.com/cleanscrape/tennis-match-data/examples/tennis-upcoming-form-head-to-head" rel="noopener noreferrer"&gt;upcoming matches with form and head-to-head&lt;/a&gt; and &lt;a href="https://apify.com/cleanscrape/tennis-match-data/examples/tennis-player-season-point-by-point" rel="noopener noreferrer"&gt;a player's season with point-by-point&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost and limits
&lt;/h2&gt;

&lt;p&gt;The base price is $1.00 per 1,000 matches. Match details (statistics, set details or point-by-point) add $1.50 per 1,000, and form and head-to-head add $0.50 per 1,000, both only when Flashscore has them for that match. The Wimbledon run above, 478 matches with statistics, comes to about $1.20 before tier discounts. Check the Pricing tab for your account's rate and set a spending limit for big runs.&lt;/p&gt;

&lt;p&gt;Coverage follows Flashscore. ATP, WTA, Challenger and Grand Slam matches have full statistics. Most ITF matches have scores but few or no statistics. Bookmaker odds and rankings aren't included, and live matches are a snapshot at collection time.&lt;/p&gt;

&lt;p&gt;If you work with an AI assistant, there's also a free &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-tennis-research" rel="noopener noreferrer"&gt;tennis research skill&lt;/a&gt; that explains the fields and how to add statistics up without mixing percentages.&lt;/p&gt;

&lt;p&gt;Questions or a reproducible problem: use the Actor's Issues tab or email &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;. CleanScrape is independent of Flashscore, the ATP and the WTA.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Read the comments before you pay for Likee reach</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sat, 03 Oct 2026 10:00:12 +0000</pubDate>
      <link>https://dev.to/cleanscrape/read-the-comments-before-you-pay-for-likee-reach-14b2</link>
      <guid>https://dev.to/cleanscrape/read-the-comments-before-you-pay-for-likee-reach-14b2</guid>
      <description>&lt;p&gt;Say you're about to pay a Likee creator to reach people in the United States. Views and likes tell you that something was watched. They don't tell you who watched it. The comments are a better clue, because people write them in their own language and about their own concerns.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://apify.com/cleanscrape/likee-scraper" rel="noopener noreferrer"&gt;CleanScrape's Likee Scraper API&lt;/a&gt; to get those comments into a spreadsheet. I'm the developer, so this is a walkthrough of my own tool, not an independent review. An AI agent wrote this walkthrough from my run, and every number in it was checked against that run.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/GnxEDPMfU_A" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a creator's recent videos
&lt;/h2&gt;

&lt;p&gt;For the example I used Likee's official US account, &lt;code&gt;@likee_usa&lt;/code&gt;. Open the Actor, paste the handle into &lt;strong&gt;Creators or video links&lt;/strong&gt;, choose &lt;strong&gt;Videos&lt;/strong&gt; and set &lt;strong&gt;Maximum results&lt;/strong&gt; to &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You don't need a Likee account, cookies or a separate API key. You do need an Apify account to run the Actor. The same input as JSON:&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;"targets"&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;"@likee_usa"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"videos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&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;The &lt;strong&gt;Videos&lt;/strong&gt; view puts each caption beside its publish date, views, likes, comment count and shares. In my run, the post with the most discussion was "Real or Mini?", with 114 comments. That's the one I wanted to read.&lt;/p&gt;

&lt;p&gt;The counts are what Likee showed at collection time. Some come from share pages, which round them (&lt;code&gt;5.90K&lt;/code&gt;). The &lt;code&gt;countPrecision&lt;/code&gt; column tells you which ones are exact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then read the comments
&lt;/h2&gt;

&lt;p&gt;Copy the video's link (in the Likee app: &lt;strong&gt;Share &amp;gt; Copy link&lt;/strong&gt;), paste it into the same field, switch to &lt;strong&gt;Comments&lt;/strong&gt; and ask for &lt;code&gt;40&lt;/code&gt;.&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;"targets"&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://likee.video/@likee_usa/video/7629882278902002999"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&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;Here's what came back. 22 of the 40 comments were in Russian. One more was in Tajik. The most-liked comment, with 37 likes, was "В лайке есть сша?!", roughly "Is there a USA on Likee?!".&lt;/p&gt;

&lt;p&gt;That doesn't prove where the viewers live. Language is a clue, not a location, and 40 comments from one video is a small sample. But if you were budgeting for an American audience, it's the kind of thing you want to see before paying, not after.&lt;/p&gt;

&lt;p&gt;A note on counting: I first counted 24 comments in Cyrillic and nearly wrote "24 in Russian". Two of them weren't. If you do this check yourself, classify the language, not just the alphabet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Export and check the report
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Export&lt;/strong&gt;, pick the &lt;strong&gt;Comments&lt;/strong&gt; view and download CSV or Excel. The Comments view includes the text, public author name, date, likes and the video each comment belongs to. Keep the ID columns as text when you import, so spreadsheets don't round the long numbers.&lt;/p&gt;

&lt;p&gt;Then open the run report. It shows how many comments were read, which inputs were checked and why the run stopped. In this run it stopped because it reached the 40-comment limit, not because the video ran out of comments. A finished run is not a complete history of a video's comments, and hidden or removed comments can't be collected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it on the creator you're actually considering
&lt;/h2&gt;

&lt;p&gt;Replace the official account with the creator you're thinking about paying. A few setups that work well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One creator's recent posts:&lt;/strong&gt; their handle, Videos, 10 results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comments on one post:&lt;/strong&gt; its Share link, Comments, 20 to 40 results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A sample across several posts:&lt;/strong&gt; their handle, Comments, &lt;strong&gt;Videos per creator&lt;/strong&gt; 3 and &lt;strong&gt;Comments per video&lt;/strong&gt; 15. &lt;strong&gt;Maximum results&lt;/strong&gt; is the total for the whole run, so set it to 45.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two ready-made examples using Likee's own accounts: &lt;a href="https://apify.com/cleanscrape/likee-scraper/examples/likee-compare-two-creators" rel="noopener noreferrer"&gt;compare two official accounts&lt;/a&gt; and &lt;a href="https://apify.com/cleanscrape/likee-scraper/examples/likee-sample-creator-comments" rel="noopener noreferrer"&gt;read a comment sample&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost and limits
&lt;/h2&gt;

&lt;p&gt;The base price is $1.95 per 1,000 saved videos or comments, with no startup fee. The 40-comment run above costs $0.078 at that rate, before any tier discount. Check the Pricing tab for your account's rate, and set a spending limit before larger runs.&lt;/p&gt;

&lt;p&gt;It collects public videos and comments only. There's no keyword or hashtag search, no private content, and no guarantee of a complete history. The maximum you set is a ceiling, not a promise that the source has that many.&lt;/p&gt;

&lt;p&gt;If you work with an AI assistant, there's also a free &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-likee-research" rel="noopener noreferrer"&gt;Likee research skill&lt;/a&gt; that explains the fields and how to do this kind of comment check without overclaiming.&lt;/p&gt;

&lt;p&gt;Questions or a reproducible problem: use the Actor's Issues tab or email &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;. CleanScrape is independent of Likee.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>marketing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A small news watchlist that doesn't send the same headlines every day</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 27 Sep 2026 17:56:29 +0000</pubDate>
      <link>https://dev.to/cleanscrape/a-small-news-watchlist-that-doesnt-send-the-same-headlines-every-day-71</link>
      <guid>https://dev.to/cleanscrape/a-small-news-watchlist-that-doesnt-send-the-same-headlines-every-day-71</guid>
      <description>&lt;p&gt;A recurring news export has an annoying failure mode: it works, but keeps handing you the same headlines.&lt;/p&gt;

&lt;p&gt;For CleanScrape's news Actor, I wanted a small watchlist to answer two separate questions: which available articles match my topic, and which of those have I not received before?&lt;/p&gt;

&lt;p&gt;I maintain &lt;a href="https://apify.com/cleanscrape/google-news-scraper" rel="noopener noreferrer"&gt;Google News and Publisher Feed Scraper&lt;/a&gt;. It is a paid Actor that collects Google News searches and public publisher feeds into an article table. It does not generate summaries or read through paywalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get a useful first export before adding a schedule
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/google-news-scraper/examples/electric-vehicle-news-quick-start" rel="noopener noreferrer"&gt;Open the electric-vehicle example&lt;/a&gt;. It looks for recent electric-vehicle news, with a maximum of 20 articles.&lt;/p&gt;

&lt;p&gt;In the form, choose the Google News edition and &lt;strong&gt;Published within&lt;/strong&gt; from the dropdowns. You do not need to remember a country code or type dates in an exact format.&lt;/p&gt;

&lt;p&gt;For an API call, the same small starting point is:&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;"queries"&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;"electric vehicles"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"edition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US:en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxArticles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resolveUrls"&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;Open &lt;strong&gt;Articles&lt;/strong&gt; to inspect the headlines, publishers, dates and links. Any summary text is an available feed snippet, not the full article body.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrow the topic without a complicated search expression
&lt;/h2&gt;

&lt;p&gt;For a more focused watch, you could keep headlines containing &lt;code&gt;recall&lt;/code&gt; or &lt;code&gt;battery fire&lt;/code&gt; and exclude &lt;code&gt;opinion&lt;/code&gt;:&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;"queries"&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;"electric vehicles"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeTerms"&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;"recall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"battery fire"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"excludeTerms"&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;"opinion"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"any"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filterScope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxArticles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;These are literal word or phrase filters, not an AI judgement about whether an article is important. They do not search full article bodies. No result can simply mean that none of the available entries matched.&lt;/p&gt;

&lt;p&gt;The Actor can also read public RSS, Atom and JSON feeds. There is a separate &lt;a href="https://apify.com/cleanscrape/google-news-scraper/examples/bbc-technology-feed-export" rel="noopener noreferrer"&gt;BBC Technology feed example&lt;/a&gt; if you want to start with a known publisher instead of Google News.&lt;/p&gt;

&lt;p&gt;One distinction is easy to miss: a Google search query does not filter a publisher feed added to the same run. The word filters apply across sources; the query itself does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then stop exporting the same articles every time
&lt;/h2&gt;

&lt;p&gt;Enable &lt;strong&gt;Return only previously undelivered articles&lt;/strong&gt; and enter a stable &lt;strong&gt;Watch name&lt;/strong&gt;. For the original broad search, that looks like:&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;"queries"&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;"electric vehicles"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"edition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US:en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxArticles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"newOnly"&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;"watchName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EV industry watch"&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;The first run exports eligible entries. Later runs using the same watch skip article identities already delivered to it. A repeat run with no new output can be doing exactly what you asked.&lt;/p&gt;

&lt;p&gt;Keep the watch name, sources and filters consistent. Use a new watch name when changing the scope. Delivery history is retained for up to 90 days, subject to storage availability; this is not a permanent archive or a system for tracking edits inside articles.&lt;/p&gt;

&lt;p&gt;To run automatically, save the configuration as an Apify task and add a schedule. Turning on the watch option does not create that schedule, send an email or post to Slack. Those are separate workflow steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two things I would check before using the export
&lt;/h2&gt;

&lt;p&gt;First, read &lt;strong&gt;Run report&lt;/strong&gt;. Feed limits, date filtering and source errors can all reduce the output. Twenty is a maximum, not a guaranteed count. If each publisher must contribute, separate runs can be better than letting the first source fill a shared cap.&lt;/p&gt;

&lt;p&gt;Second, check link status. Publisher-link lookup is best effort. If it cannot resolve a direct URL, the row retains its Google News link and reports that status. It is still a delivered, billable article. This is more useful than silently dropping the headline, but it matters if your next step requires direct publisher URLs.&lt;/p&gt;

&lt;p&gt;At the current base price, 20 delivered articles cost &lt;strong&gt;$0.019&lt;/strong&gt;, with no startup fee. The examples have a $0.05 spending cap. Previously delivered watch entries and filtered-out entries do not generate article charges.&lt;/p&gt;

&lt;p&gt;The intended result is a manageable reading queue for your own research or reporting workflow. It is not a complete news archive, a verified factual briefing or a substitute for reading the source.&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Google and the publishers. Public feed availability does not grant unrestricted republication rights. Questions or reproducible issues are welcome in the Actor's Issues tab or at &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a reading brief from the saved articles
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-news-research" rel="noopener noreferrer"&gt;Google News and feed research skill&lt;/a&gt; covers what happens after export. It helps a compatible assistant organise the available headlines and snippets into a sourced reading list, without presenting feed text as a full article or a verified account of events.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this article export only. Group the main topics, keep publisher links and dates, and flag unresolved links or missing context. Do not fetch full articles or start another run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The instructions are free and do not create a schedule. Fresh collection and any assistant usage have their own costs. Keep the underlying sources handy when a detail matters.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Shopify review is not always about the product page you're looking at</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 27 Sep 2026 17:55:24 +0000</pubDate>
      <link>https://dev.to/cleanscrape/a-shopify-review-is-not-always-about-the-product-page-youre-looking-at-11io</link>
      <guid>https://dev.to/cleanscrape/a-shopify-review-is-not-always-about-the-product-page-youre-looking-at-11io</guid>
      <description>&lt;p&gt;One detail worth checking before analysing Shopify reviews: the reviews displayed on a product page may not all belong to that exact product.&lt;/p&gt;

&lt;p&gt;During validation of CleanScrape's review scraper, one clothing product widget exposed 675 reviews. The source flagged 619 of them as shared from its product group. Treating that whole export as feedback about a single item would have given the wrong impression.&lt;/p&gt;

&lt;p&gt;That is why I wanted product attribution in the output, not just a rating and a block of text. I maintain &lt;a href="https://apify.com/cleanscrape/shopify-reviews-scraper" rel="noopener noreferrer"&gt;Shopify Product Reviews Scraper&lt;/a&gt;, a paid Actor that currently supports public &lt;strong&gt;Judge.me and Okendo&lt;/strong&gt; integrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video walkthrough (added October 5, 2026):&lt;/strong&gt; the same check on Magic Spoon's Strawberry Cheesecake cereal page, where only 56 of 1,000 reviews are about that cereal.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ETWdyJHqIUQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with one product URL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/shopify-reviews-scraper/examples/cleanscrape-shopify-reviews-quick-start" rel="noopener noreferrer"&gt;Open the 25-review example&lt;/a&gt;. It uses an Owala product page. Replace that URL with the product you want to investigate.&lt;/p&gt;

&lt;p&gt;You do not need to identify the review provider, find a shop ID or supply a merchant API key. The Actor checks the public integration and reports which supported source it found.&lt;/p&gt;

&lt;p&gt;Here is a small API input that keeps all star ratings:&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;"productUrls"&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://owalalife.com/products/freesip"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxReviewsPerProduct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxTotalReviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ratings"&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;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5"&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="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, 100 is the per-product scan budget and 25 is the total export limit. They do different jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering low ratings does not search the whole history
&lt;/h2&gt;

&lt;p&gt;Suppose you change &lt;code&gt;ratings&lt;/code&gt; to &lt;code&gt;["1", "2"]&lt;/code&gt; while keeping the scan budget at 100.&lt;/p&gt;

&lt;p&gt;The Actor exports matching reviews found within those scanned records. It does not promise to keep searching until it finds 25 low-rated reviews. Eight matching rows, or none, can be a valid result.&lt;/p&gt;

&lt;p&gt;I would first export a small unfiltered sample to check the content and attribution, then narrow the ratings. Otherwise it is easy to mistake a restrictive filter for a broken source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the attribution columns in your spreadsheet
&lt;/h2&gt;

&lt;p&gt;Open the review output and inspect &lt;strong&gt;Product attribution&lt;/strong&gt; alongside the review text. These fields are particularly 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;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;productUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The product page requested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;reviewedProductName&lt;/code&gt; and &lt;code&gt;reviewedProductUrl&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The reviewed product identified by the source, when supplied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;isGroupedReview&lt;/code&gt; and &lt;code&gt;isBundleReview&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Available grouping context; null means it was not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;provider&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whether the row came from Judge.me or Okendo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recordKey&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A stable key for joining your exports&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a product-feedback analysis, I would separate clearly shared reviews from product-specific feedback and keep unknown attribution as its own category. I would not quietly turn unknown into false.&lt;/p&gt;

&lt;p&gt;Once the columns make sense, export CSV, Excel or JSON. The Actor collects the reviews; it does not perform sentiment analysis or decide which complaints matter to your business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check what the source actually exposed
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Coverage report&lt;/strong&gt; records the source, scanned and exported counts, and why collection stopped. A successful run does not establish that the full review history was available.&lt;/p&gt;

&lt;p&gt;Some integrations expose only embedded reviews or stop pagination early. An unsupported source is not proof that the product has zero reviews. Missing titles, dates or verification badges stay missing rather than being guessed.&lt;/p&gt;

&lt;p&gt;Support is currently limited to recognizable public Judge.me and Okendo integrations. A Shopify store using another review app is not covered just because it runs on Shopify. This also does not collect Shopify App Store app reviews.&lt;/p&gt;

&lt;p&gt;The current base price is &lt;strong&gt;$0.95 per 1,000 exported reviews&lt;/strong&gt;, with no startup or rating-filter add-on fee. A 25-review export costs $0.02375 before subscription discounts. The example has a $0.05 cap. A fresh run can return and charge for reviews collected in an earlier run; this is an export tool, not a changes-only monitor.&lt;/p&gt;

&lt;p&gt;If you are combining reviews across stores, the attribution is worth keeping even when it complicates the spreadsheet. It is better to see that uncertainty than to build a neat analysis around the wrong product.&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Shopify, Judge.me, Okendo and the merchants used as examples. For a reproducible issue, share a run ID and public product URL through the Actor's Issues tab or &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep that distinction when using an assistant
&lt;/h2&gt;

&lt;p&gt;I added a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-shopify-reviews" rel="noopener noreferrer"&gt;Shopify review research skill&lt;/a&gt; for this part of the workflow. It tells a compatible assistant to retain Judge.me or Okendo attribution, separate shared product-group reviews, and keep unknown scope visible rather than quietly treating every row as exact-product feedback.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Analyse this saved review export. Separate exact-product, shared and unknown attribution before summarising complaints. Show the review IDs behind each finding. Do not collect more reviews.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This works from your existing files. The skill is free; it does not make fresh Actor runs or your assistant's own usage free.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>ecommerce</category>
      <category>data</category>
    </item>
    <item>
      <title>From Pinterest search to a usable research spreadsheet</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 27 Sep 2026 17:54:12 +0000</pubDate>
      <link>https://dev.to/cleanscrape/from-pinterest-search-to-a-usable-research-spreadsheet-34e3</link>
      <guid>https://dev.to/cleanscrape/from-pinterest-search-to-a-usable-research-spreadsheet-34e3</guid>
      <description>&lt;p&gt;Pinterest is useful for finding ideas. Keeping track of the websites behind those ideas is a different job.&lt;/p&gt;

&lt;p&gt;For a research project, I would rather have a small list I can inspect and revisit than a folder full of disconnected images. That is the workflow behind CleanScrape's &lt;a href="https://apify.com/cleanscrape/pinterest-scraper" rel="noopener noreferrer"&gt;Pinterest Actor&lt;/a&gt;: collect the public pins, keep the available source links, and make the result usable outside Pinterest.&lt;/p&gt;

&lt;p&gt;I maintain the Actor, and it is a paid tool. This walkthrough uses home-office ideas as an example.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/bl7tb0c8AG8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  A focused search, rather than whatever looks vaguely related
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/pinterest-scraper/examples/pinterest-home-office-research" rel="noopener noreferrer"&gt;Open the home-office example&lt;/a&gt;. It asks for up to 50 pins, selects &lt;strong&gt;All query words&lt;/strong&gt;, and enables additional public pin details.&lt;/p&gt;

&lt;p&gt;The matching setting matters. Pinterest can return broad recommendations. &lt;strong&gt;All query words&lt;/strong&gt; requires the search words to appear in the pin's title, description or alt text. &lt;strong&gt;Exact phrase&lt;/strong&gt; is stricter; Pinterest relevance is broader.&lt;/p&gt;

&lt;p&gt;Neither strict option understands the image itself. A relevant desk setup can be excluded if its accompanying text never says "home office." That is a trade-off, not a reason to call the search exhaustive.&lt;/p&gt;

&lt;p&gt;For a minimal API input:&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;"searchTerms"&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;"home office"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxPins"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchMatching"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allWords"&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;The ready-made example also enables the additional public detail lookup. You do not need Pinterest cookies, a login or a numeric board ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the visual view before opening the spreadsheet
&lt;/h2&gt;

&lt;p&gt;After the run, open &lt;strong&gt;Research view&lt;/strong&gt; in Output, then the &lt;strong&gt;RESEARCH_VIEW&lt;/strong&gt; record. It shows a visual preview of the first 200 exported pins, along with destination-domain counts for the export.&lt;/p&gt;

&lt;p&gt;This is a convenient place to decide whether the search is useful before doing more work with it. If most results are off-topic, change the matching or filter settings rather than immediately increasing the limit.&lt;/p&gt;

&lt;p&gt;The recorded 50-pin demo contained 13 external source links across 12 destination domains. That describes that run, not a guaranteed hit rate. Some pins do not expose an external destination at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the Pinterest link and the destination link separate
&lt;/h2&gt;

&lt;p&gt;For a spreadsheet, select &lt;strong&gt;Research essentials&lt;/strong&gt; in the export dialog and choose Excel or CSV. Use &lt;strong&gt;All fields&lt;/strong&gt; if you want the complete dataset.&lt;/p&gt;

&lt;p&gt;The distinction I would preserve downstream is:&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 points to&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pinUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Pinterest pin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outboundUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The external destination, if supplied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outboundDomain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;That destination's domain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An empty destination is not a failed attempt to invent a website. It means the source did not provide one in the collected data. Similarly, a missing engagement count is not zero.&lt;/p&gt;

&lt;p&gt;You can sort by domain to find recurring source websites, then open the links to check the original material. Domain frequency in one export is not evidence of market share or popularity across Pinterest.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few limits worth keeping in the notes
&lt;/h2&gt;

&lt;p&gt;The Actor accepts public searches, boards, profile feeds and individual pins. A profile feed can include saved pins; it is not necessarily a list of that person's original work. Private boards and comment text are outside the scope.&lt;/p&gt;

&lt;p&gt;Image and video URLs are references, not a license to reuse the media. Saves, comments and shares are also not views, sales or demand estimates.&lt;/p&gt;

&lt;p&gt;At the current base rate, 50 delivered pins cost &lt;strong&gt;$0.0625&lt;/strong&gt;, with no startup or separate detail-lookup fee. The example has a $0.10 spending cap. Check &lt;strong&gt;Run report&lt;/strong&gt; for filtering, source failures and stopping reasons if fewer pins arrive than requested.&lt;/p&gt;

&lt;p&gt;The point is to get from a visual search to a research list you can actually work through. The same steps work with your own topic; home offices just make the process easy to see.&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Pinterest. If a public input behaves unexpectedly, the Actor's Issues tab is the best place to share the run ID and what you expected, without passwords or tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organise the research list with an assistant
&lt;/h2&gt;

&lt;p&gt;I published a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-pinterest-research" rel="noopener noreferrer"&gt;Pinterest research skill&lt;/a&gt; for turning the saved export into a more usable list. A compatible assistant can group destination domains and content themes while keeping missing destinations, attribution and engagement limits visible.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this pin export to make a home-office reading list grouped by destination website. Keep pins with no destination in a separate group. Do not download images or run another scrape.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The skill is free; your assistant may have its own usage charges. It does not grant rights to reuse the pin media, and a frequently appearing domain is not automatically a popular or authoritative source.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>data</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Comparing Google Hotels booking offers without losing the stay details</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 27 Sep 2026 17:48:44 +0000</pubDate>
      <link>https://dev.to/cleanscrape/comparing-google-hotels-booking-offers-without-losing-the-stay-details-1hh2</link>
      <guid>https://dev.to/cleanscrape/comparing-google-hotels-booking-offers-without-losing-the-stay-details-1hh2</guid>
      <description>&lt;p&gt;Comparing hotel prices looks straightforward until the tabs stop agreeing. One quote is per night, another is for the whole stay, and a cheaper offer may have a different cancellation policy.&lt;/p&gt;

&lt;p&gt;For CleanScrape's Google Hotels Actor, I wanted the export to keep the stay details beside the prices. A spreadsheet is only useful if you can still tell what each number refers to.&lt;/p&gt;

&lt;p&gt;Here's a small London example, using a real run. I maintain &lt;a href="https://apify.com/cleanscrape/google-hotels-scraper" rel="noopener noreferrer"&gt;this paid Actor&lt;/a&gt; under CleanScrape.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/QrzboGuj05o" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with five hotels
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/google-hotels-scraper/examples/google-hotels-london-price-comparison" rel="noopener noreferrer"&gt;Open the London example&lt;/a&gt;. It is prefilled for a two-night stay, two adults and prices in British pounds. You can change the destination before running it.&lt;/p&gt;

&lt;p&gt;In the form, use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Place searches:&lt;/strong&gt; &lt;code&gt;hotels in London&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When is the stay?:&lt;/strong&gt; In 30 days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Number of nights:&lt;/strong&gt; 2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adults:&lt;/strong&gt; 2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price currency:&lt;/strong&gt; British pound&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximum hotel results for the whole run:&lt;/strong&gt; 5&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The example also has a $0.02 spending cap. The result limit is a maximum, not a promise that every search can supply that many hotels.&lt;/p&gt;

&lt;p&gt;The recorded run returned five hotel rows and 133 organic booking-provider offers. It was collected on September 27, 2026, for October 27-29. Those are historical quotes, not prices you can necessarily book now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two tables, two different jobs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hotel prices&lt;/strong&gt; is the shortlist. It puts the hotel name, check-in, check-out, adults, currency, nightly price and stay total together. I would start there to remove options that clearly do not fit the trip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider offers&lt;/strong&gt; goes one level deeper: which booking sites supplied offers for each hotel, and what prices did they show?&lt;/p&gt;

&lt;p&gt;Those provider rows are included in the hotel result. Expanding the provider table does not turn five hotels into 133 separately billed hotel results.&lt;/p&gt;

&lt;p&gt;There is an important distinction here: the Actor verifies the stay context, but it does not establish that every offer is for an equivalent room. A refundable room and a non-refundable room should not be treated as interchangeable just because the dates match. Taxes and other terms can differ too. Confirm the final price with the provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  The export step is easy to miss
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Export&lt;/strong&gt;, then select &lt;strong&gt;Provider offers again inside the dialog&lt;/strong&gt; before choosing Excel or CSV. Selecting the table on screen is not enough to assume the export dialog has selected the same view.&lt;/p&gt;

&lt;p&gt;Once downloaded, you can sort quotes within each hotel and work through the options. Keep the hotel, dates, guests and currency columns; they are the context that makes the comparison useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this run does not establish
&lt;/h2&gt;

&lt;p&gt;A place search samples the first source results page. Five returned hotels are not the five cheapest hotels in London, and they are not an inventory of the city.&lt;/p&gt;

&lt;p&gt;Some offer lists can also be partial. Open &lt;strong&gt;Run report&lt;/strong&gt; and read it alongside the dataset before treating an export as complete. The video deliberately leaves that coverage information visible.&lt;/p&gt;

&lt;p&gt;At the current base prices, five delivered hotels and one start at the default memory cost &lt;strong&gt;$0.01075&lt;/strong&gt;: $1.95 per 1,000 hotel results, plus $0.001 for that start. Subscription discounts may apply; check the Actor's Pricing tab before a larger run.&lt;/p&gt;

&lt;p&gt;For me, the useful outcome is a shortlist with enough context to investigate, not a spreadsheet that pretends to make the booking decision. Try the small example first and see whether those fields fit your comparison.&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Google and the booking providers. Questions or reproducible issues can go in the Actor's Issues tab or to &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare the exported offers with an assistant
&lt;/h2&gt;

&lt;p&gt;There is also a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-hotel-comparison" rel="noopener noreferrer"&gt;Google Hotels comparison skill&lt;/a&gt; for this step. It guides a compatible assistant to compare offers only within the right stay and currency, preserve the source totals, and point out where room terms or coverage still need checking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compare these saved hotel offers for the same dates, guests and currency. Show the lowest observed totals and explain which offers are not directly comparable. Do not collect new quotes or make a booking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The instructions are free. Working with the export needs no new Apify run, although your assistant may have its own usage charges. The result is a shortlist to investigate, not a live booking quote.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>tutorial</category>
      <category>data</category>
    </item>
    <item>
      <title>Export App Store and Google Play reviews into one spreadsheet</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:45:58 +0000</pubDate>
      <link>https://dev.to/cleanscrape/export-app-store-and-google-play-reviews-into-one-spreadsheet-1c1l</link>
      <guid>https://dev.to/cleanscrape/export-app-store-and-google-play-reviews-into-one-spreadsheet-1c1l</guid>
      <description>&lt;p&gt;When an app is available on iOS and Android, I want to read the feedback from both stores without switching between pages. Are people raising the same issues, or does one platform need a closer look?&lt;/p&gt;

&lt;p&gt;I built CleanScrape's &lt;a href="https://apify.com/cleanscrape/app-store-reviews-scraper" rel="noopener noreferrer"&gt;App Store and Google Play Reviews Scraper&lt;/a&gt; to put those reviews into one table. This walkthrough uses my paid Actor to collect a small sample, then shows how to compare the comments in a spreadsheet. The comparison is something you do after export, not an automatic analysis feature.&lt;/p&gt;

&lt;p&gt;Let's use Spotify as an example. You can replace its store links with those for your own app or another publicly listed app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the export workflow
&lt;/h2&gt;

&lt;p&gt;The short demo shows the app links, regional settings, review table and spreadsheet export. It requests up to 20 reviews per store. The comparison steps below pick up where the video leaves off.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/WpWDcEdP3Rs" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Get your first small export
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/app-store-reviews-scraper/examples/export-spotify-app-store-reviews" rel="noopener noreferrer"&gt;Open the ready-made Spotify example&lt;/a&gt;. Its preset is 100 reviews per store; change &lt;strong&gt;Maximum reviews&lt;/strong&gt; to &lt;strong&gt;20&lt;/strong&gt; to follow the video.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep both stores selected. For another app, paste its Google Play and Apple App Store links into the corresponding fields.&lt;/li&gt;
&lt;li&gt;Choose the country and Google Play language by name. The country selects a storefront, not the reviewer's verified location; the language setting does not translate comments.&lt;/li&gt;
&lt;li&gt;Use newest reviews and keep the 1 GB memory setting. Set a spending limit before starting.&lt;/li&gt;
&lt;li&gt;After the run, open &lt;strong&gt;Review essentials&lt;/strong&gt; for the compact table. Open &lt;strong&gt;Run summary and field guide&lt;/strong&gt; to check that both requested stores returned data.&lt;/li&gt;
&lt;li&gt;Export CSV or Excel. Keep the source column in your spreadsheet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The maximum is per store: 20 plus 20 means up to 40 reviews. Availability can produce fewer. If Apple supplies an unverified empty feed, the Actor now reports a source error rather than implying that the app has no reviews. A Google Play export can still succeed in that run, so read the per-store report before comparing platforms.&lt;/p&gt;

&lt;p&gt;For an API workflow, the same small request is:&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;"store"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"both"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"googlePlayAppId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://play.google.com/store/apps/details?id=com.spotify.music"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appStoreId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://apps.apple.com/us/app/spotify/id324684580"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxReviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newest"&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;Existing package names and numeric app IDs still work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare the feedback, not just the averages
&lt;/h2&gt;

&lt;p&gt;Start with a specific question, such as: &lt;strong&gt;Are the low-rated reviews describing similar problems on iOS and Android?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filter rating to 1 or 2 and read the review text. Keep source, date and appVersion visible.&lt;/li&gt;
&lt;li&gt;Add your own issue column. Use labels that fit the comments you actually read, such as sign-in, playback or billing. Those are possible labels, not findings from this sample.&lt;/li&gt;
&lt;li&gt;Group or make a pivot table by issue and source, counting review IDs. This gives you a reading list of recurring themes in the downloaded sample.&lt;/li&gt;
&lt;li&gt;Go back to the original comments before drawing a conclusion. A short negative review may not explain its cause. If appVersion is available, compare versions within each store, not as interchangeable iOS and Android release numbers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not sentiment analysis, a satisfaction score or proof that one release caused a complaint. Twenty recent reviews per store can help you decide what to investigate; it cannot establish how common an issue is among all users. The two exports may also cover different date spans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know what the columns mean
&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;How I would use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;source&lt;/td&gt;
&lt;td&gt;Keep iOS and Android feedback separate while using the same spreadsheet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rating and text&lt;/td&gt;
&lt;td&gt;Find comments to read, then understand the actual feedback.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;Check the source timestamp; Apple's value is an update time, not necessarily the original publication date.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appVersion&lt;/td&gt;
&lt;td&gt;Inspect version-specific feedback when the source supplies it. Missing versions stay empty.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reviewId&lt;/td&gt;
&lt;td&gt;Identify reviews when joining or updating exports.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;developerReply&lt;/td&gt;
&lt;td&gt;Read available Google Play replies. Apple replies are not supplied by this feed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Google Play titles are also empty in this adapter. Missing source fields stay empty rather than being filled with guesses. Choose the full &lt;strong&gt;Reviews&lt;/strong&gt; view if you need every output field.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the whole run costs
&lt;/h2&gt;

&lt;p&gt;At the current base rate and 1 GB memory:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Delivered output&lt;/th&gt;
&lt;th&gt;Result charges&lt;/th&gt;
&lt;th&gt;Startup&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;40 reviews&lt;/td&gt;
&lt;td&gt;$0.008&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.018&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200 reviews&lt;/td&gt;
&lt;td&gt;$0.04&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.05&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The second row is the existing preset if it returns 100 reviews from each store. Startup is charged even when no reviews return. Selecting more memory increases the startup charge; saved tasks can retain their own memory setting. Filtering rows in Excel does not change the number already delivered and billed.&lt;/p&gt;

&lt;p&gt;These are base prices before subscription discounts, checked on 27 September 2026. See the Actor's &lt;a href="https://apify.com/cleanscrape/app-store-reviews-scraper/pricing" rel="noopener noreferrer"&gt;Pricing tab&lt;/a&gt; for your applicable rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you repeat the export
&lt;/h2&gt;

&lt;p&gt;Apple's public feed is a recent, limited source, not a complete archive. Source availability can change. Increasing the maximum does not guarantee more history.&lt;/p&gt;

&lt;p&gt;The Actor does not maintain review history across separate runs. Where a review ID exists, use the combination of source, appId, country and reviewId as a starting key. Update edited reviews instead of appending duplicates, and handle missing IDs separately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/app-store-reviews-scraper/examples/export-spotify-app-store-reviews" rel="noopener noreferrer"&gt;Open the example&lt;/a&gt;, change the app links and keep the first run small. No store login or personal cookies are needed. CleanScrape is independent of Apple, Google and Spotify.&lt;/p&gt;

&lt;p&gt;If you use review exports, what makes them useful after the download: comparing platforms, reviewing a release, or feeding another workflow? Practical feedback helps me choose what to improve. For a bug, open an Actor issue with the run ID and a non-sensitive input example. Keep tokens and credentials out of comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the same export in an assistant
&lt;/h2&gt;

&lt;p&gt;I also published a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-app-reviews" rel="noopener noreferrer"&gt;free app-review skill&lt;/a&gt; for assistants that support agent skills. It gives the assistant a way to compare the two stores without losing the review IDs or mistaking a small sample for every user's opinion.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use these saved review exports only. Compare iOS and Android complaints, show the rating counts for each store, and flag missing data. Do not start a new run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also supply two snapshots to find newly observed or edited reviews. This is analysis of your files, not an automatic monitoring service. The instructions are free; fresh Actor runs and your assistant's own usage are separate.&lt;/p&gt;

</description>
      <category>webscraping</category>
    </item>
    <item>
      <title>Compare Google Trends terms in a spreadsheet without confusing interest with search volume</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:44:55 +0000</pubDate>
      <link>https://dev.to/cleanscrape/compare-google-trends-terms-in-a-spreadsheet-without-confusing-interest-with-search-volume-4lmm</link>
      <guid>https://dev.to/cleanscrape/compare-google-trends-terms-in-a-spreadsheet-without-confusing-interest-with-search-volume-4lmm</guid>
      <description>&lt;p&gt;I'm building CleanScrape for people who want to use web data in their own reports and tools. The &lt;a href="https://apify.com/cleanscrape/google-trends-scraper" rel="noopener noreferrer"&gt;Google Trends Scraper&lt;/a&gt; is one part of that: it returns Trends observations as rows you can export or retrieve through the API.&lt;/p&gt;

&lt;p&gt;For this post, I'll compare ChatGPT and Claude in a spreadsheet. There is one detail I want to get out of the way first: a Trends value of 100 does not mean 100 searches. It is a relative interest score within the requested comparison. That meaning needs to survive the CSV export.&lt;/p&gt;

&lt;p&gt;This walkthrough uses my paid Actor on Apify. I've included the cost calculation below so you can judge whether it fits your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch a quick example
&lt;/h2&gt;

&lt;p&gt;Let's use a coffee shop as an example. In this short demo, I compare "iced coffee" and "cold brew" in the United States over the past 12 months, export the timeline and plot the completed weeks.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/GBEaKKHMJKs" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The video shows the real input form, output table and export dialog. The chart is made separately from the exported rows, with the incomplete week left out. You can use the same steps for a personal interest, a business idea or a brand. The written example below uses ChatGPT and Claude over three months instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request both terms together
&lt;/h2&gt;

&lt;p&gt;This example compares ChatGPT and Claude in the US over the past three months. In the form, add both search terms, choose United States and Past 3 months, and select only Interest over time. If you prefer JSON input, use:&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;"searchTerms"&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;"ChatGPT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Claude"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dataTypes"&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;"interest_over_time"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"geo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeframe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"today 3-m"&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;You need an Apify account, but no Google login. The Actor uses residential Apify Proxy by default for these requests. It accesses Google Trends website endpoints; it is not Google's official API or an affiliated Google product.&lt;/p&gt;

&lt;p&gt;I recommend starting with just the timeline. It keeps the output easier to read and avoids paying for result types you are not using yet.&lt;/p&gt;

&lt;p&gt;Keep both terms in the same request. Pulling each term independently can give you separately normalized series that are not directly comparable. Also note that these inputs are search terms, not a guarantee that every search relates to a particular company or product.&lt;/p&gt;

&lt;p&gt;Set a run spending limit and check the current pricing before selecting Start. You can also find this comparison as an example task on the Actor page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn the rows into a chart
&lt;/h2&gt;

&lt;p&gt;Once the run finishes, open Output and export CSV or Excel. Timeline rows include:&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;How to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keyword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Separate the two series&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Human-readable source date label&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timestamp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unix timestamp in seconds, returned as a string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Relative search interest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isPartial&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whether Google marks the interval as partial&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In your spreadsheet, create a pivot table with date as the rows, keyword as the columns and value as the measure. Sort chronologically; if the imported date labels sort as text, convert them to dates or sort by the numeric timestamp first. Insert a line chart from that table.&lt;/p&gt;

&lt;p&gt;Use the pivot only on the timeline rows. If you later request related queries or regional data, filter by &lt;code&gt;dataType&lt;/code&gt; first. Those rows have different meanings.&lt;/p&gt;

&lt;p&gt;The Actor exports data, not a finished chart. You choose the chart, title and interpretation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the report before trusting the chart
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;RUN_REPORT&lt;/code&gt; in the run's key-value store. Each requested feature has its own status and row count. An empty result is not evidence that nobody searched for the term; a failed request is not a zero.&lt;/p&gt;

&lt;p&gt;Google chooses the returned time intervals. Three months does not guarantee exactly 90 observations. A zero can reflect insufficient data, and a partial interval should not be presented as a completed period without qualification.&lt;/p&gt;

&lt;p&gt;I would describe the chart as a comparison of relative search interest, not as a comparison of sales, active users or market share. The export cannot establish those things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Count rows when estimating the cost
&lt;/h2&gt;

&lt;p&gt;Each keyword at each returned timestamp is one billable row. If Google returns 90 timestamps for two terms, that is 180 rows.&lt;/p&gt;

&lt;p&gt;At the base rate of $0.003 per row, those rows cost $0.54. Startup adds $0.05 per allocated GB, with a minimum of one startup event. At the current 1 GB default, the total for that example is &lt;strong&gt;$0.59&lt;/strong&gt; before subscription discounts. Existing saved tasks may retain a different memory setting.&lt;/p&gt;

&lt;p&gt;That is a calculation, not a promised row count. Startup is charged even when no rows are returned, and other selected data types add their own rows. Subscription discounts can reduce the rates. Pricing and default memory were checked on 22 September 2026; use the &lt;a href="https://apify.com/cleanscrape/google-trends-scraper/pricing" rel="noopener noreferrer"&gt;Pricing tab&lt;/a&gt; for current figures.&lt;/p&gt;

&lt;p&gt;If you are comparing tools, check the cost for the same task. One service may call an entire keyword history a result; another may count each observation. I do not want the per-result headline to obscure that difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try your own comparison
&lt;/h2&gt;

&lt;p&gt;Replace the two terms with a comparison relevant to your work, keeping the geography and time window consistent. Save the input alongside the export so you can explain what the chart measures later.&lt;/p&gt;

&lt;p&gt;The Actor also supports related queries, regional interest and a current trending-searches feed. Related topics are optional and availability-limited: Google may return no topics even for familiar terms. I would not make a reporting workflow depend on that field always being populated.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://apify.com/cleanscrape/google-trends-scraper" rel="noopener noreferrer"&gt;full documentation and example tasks&lt;/a&gt; are on Apify. I'd be interested to hear what you need after the export: a weekly comparison, a dashboard, or simply a file you can inspect. It helps me understand where the tool is useful and where the next bit of friction is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare the comparison with an assistant
&lt;/h2&gt;

&lt;p&gt;If you would rather have an assistant prepare the table, I wrote a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-google-trends" rel="noopener noreferrer"&gt;Google Trends research skill&lt;/a&gt;. It keeps the same checks from this post: one request context, timeline rows only, incomplete intervals labelled, and missing observations left as gaps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this Trends export and its saved input. Make a chart-ready table for the two terms, exclude incomplete intervals, and explain what the scores mean. Do not collect fresh data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The skill is free to use with a compatible assistant. It does not need another Apify run to analyse an existing file; your assistant may have its own usage charges.&lt;/p&gt;

</description>
      <category>webscraping</category>
    </item>
    <item>
      <title>Track "Map Your Show" exhibitor changes without comparing spreadsheets by hand</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:43:37 +0000</pubDate>
      <link>https://dev.to/cleanscrape/track-map-your-show-exhibitor-changes-without-comparing-spreadsheets-by-hand-2ff5</link>
      <guid>https://dev.to/cleanscrape/track-map-your-show-exhibitor-changes-without-comparing-spreadsheets-by-hand-2ff5</guid>
      <description>&lt;p&gt;I'm building CleanScrape as a small collection of practical data tools. With the &lt;a href="https://apify.com/cleanscrape/event-exhibitor-monitor" rel="noopener noreferrer"&gt;Event Exhibitor Scraper and Change Monitor&lt;/a&gt;, I want to make one fairly specific task easier: export an exhibitor list, then see what changed without comparing the next spreadsheet by hand.&lt;/p&gt;

&lt;p&gt;A new company, a different booth or an updated description can be useful information when you are planning an event visit or researching suppliers. But I do not want an incomplete download to look like dozens of companies disappearing. That is why the monitoring checks matter as much as the export.&lt;/p&gt;

&lt;p&gt;I'll show a small snapshot first, then how to keep a baseline for later comparisons. This is a paid Actor on Apify. Its scope is public "Map Your Show" &lt;code&gt;8_0&lt;/code&gt; directories on &lt;code&gt;EVENT.mapyourshow.com&lt;/code&gt;, not every conference website. It does not provide attendee or hidden contact data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video walkthrough (added October 5, 2026):&lt;/strong&gt; the same workflow on IAAPA Expo 2026, from an export of all 1,392 exhibitors to the changes between September 27 and October 4.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/TZ2btRGqKI8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  First, export a small list
&lt;/h2&gt;

&lt;p&gt;Open the Actor in Apify and use this input:&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;"eventUrls"&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="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://iaapaexpo26.mapyourshow.com/8_0/explore/exhibitor-alphalist.cfm"&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;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snapshot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxExhibitorsPerEvent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;Review the Pricing tab and set a run spending limit before starting. This requests up to 100 exhibitors, with optional profile enrichment switched off. The IAAPA example depends on that edition's directory remaining public.&lt;/p&gt;

&lt;p&gt;After the run finishes, open Output and export CSV or Excel. Rows include company names, booths, listing descriptions and source links where available. Booths are arrays in the JSON because an exhibitor can have more than one.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;SUMMARY&lt;/code&gt; in the run's key-value store as well. A &lt;code&gt;capped_snapshot&lt;/code&gt; is a deliberately limited sample, not a claim that you collected the entire directory. With optional details off, website and location fields can be null.&lt;/p&gt;

&lt;p&gt;At the base rate, a snapshot returning 100 records costs &lt;strong&gt;$0.20&lt;/strong&gt;, with no startup fee. I recommend starting here so you can see whether the fields are useful before setting up a recurring check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a baseline when you need comparisons
&lt;/h2&gt;

&lt;p&gt;For monitoring, use a stable watchlist name and a source-record limit large enough for the whole directory:&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;"eventUrls"&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://iaapaexpo26.mapyourshow.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"monitor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"watchlistName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"iaapa-research-2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxExhibitorsPerEvent"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&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="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;This is not another 100-row sample. The first complete monitoring run exports the baseline, and those rows are billable. A directory with 1,000 exhibitors costs $2.05 at the base rate for that first check, without optional details. A larger baseline costs more.&lt;/p&gt;

&lt;p&gt;The Actor needs permission to create and access its named watchlist storage in the run owner's account. Reuse the same watchlist name and settings on later runs. You can save an Apify Task and add a schedule, but the input alone does not create one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a later run tells you
&lt;/h2&gt;

&lt;p&gt;Later runs export changes rather than another copy of the baseline. Change records distinguish additions, updates and confirmed absence. For an update, &lt;code&gt;changedFields&lt;/code&gt; tells you what changed, and &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; hold the compared values.&lt;/p&gt;

&lt;p&gt;The following is an &lt;strong&gt;illustration&lt;/strong&gt;, not a report about a real exhibitor:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Previous booth&lt;/th&gt;
&lt;th&gt;Current booth&lt;/th&gt;
&lt;th&gt;Interpretation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Example Manufacturing&lt;/td&gt;
&lt;td&gt;B12&lt;/td&gt;
&lt;td&gt;C08&lt;/td&gt;
&lt;td&gt;Booth field changed between checks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An unchanged directory can correctly produce zero change rows. The completed monitoring check still costs $0.05 per directory at the base rate. A check returning ten changes costs $0.07 without optional details.&lt;/p&gt;

&lt;p&gt;Those prices are stated as of 15 September 2026, before subscription discounts. The &lt;a href="https://apify.com/cleanscrape/event-exhibitor-monitor/pricing" rel="noopener noreferrer"&gt;Pricing tab&lt;/a&gt; has current rates. Optional enrichment is separately charged when enabled and public details are extracted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I would not treat one missing result as a removal
&lt;/h2&gt;

&lt;p&gt;The monitor requires a complete scan that reconciles retrieved IDs with the directory's reported total. Failed requests, overlapping pages and incompatible source responses must not silently become a new baseline.&lt;/p&gt;

&lt;p&gt;A company is reported as &lt;code&gt;no_longer_listed&lt;/code&gt; only after two consecutive complete checks miss it. Even then, that means it was no longer observed in the directory, not that it definitely withdrew from the event.&lt;/p&gt;

&lt;p&gt;There is an additional guard against sudden mass disappearance: when a baseline has at least ten exhibitors and more than 40% disappear at once, the check is quarantined rather than advancing the baseline. Empty source directories are treated as unavailable.&lt;/p&gt;

&lt;p&gt;I prefer that cautious behavior to a convincing-looking list of removals based on a failed fetch. It still has limits: the website can change between requests, and a change that happens and reverts between runs can go unseen. These checks do not make the snapshot perfectly atomic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before adding notifications
&lt;/h2&gt;

&lt;p&gt;Run the workflow manually first and inspect &lt;code&gt;SUMMARY&lt;/code&gt;. A run covering multiple events can have mixed outcomes. Monitoring supports at most 5,000 source records per event; optional details support at most 500 matched profiles per event.&lt;/p&gt;

&lt;p&gt;A retry after interrupted delivery can repeat records, so use &lt;code&gt;recordId&lt;/code&gt; for downstream deduplication. Do not assume exactly-once delivery. If you use keyword filters, a company leaving the matching scope is not necessarily leaving the directory.&lt;/p&gt;

&lt;p&gt;Email, Slack and CRM actions belong in a separate integration; the Actor does not send messages or contact exhibitors. Start with the &lt;a href="https://apify.com/cleanscrape/event-exhibitor-monitor" rel="noopener noreferrer"&gt;snapshot example&lt;/a&gt;, inspect the fields, and add monitoring only if you need it.&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Map Your Show and the event organizers. Public availability does not remove the need to respect source terms and data-use restrictions.&lt;/p&gt;

&lt;p&gt;I'd like to hear from people who actually work with exhibitor lists. Which changes affect your planning enough to be worth tracking: new companies, booth moves, updated descriptions, or something else?&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn the export into a visit shortlist
&lt;/h2&gt;

&lt;p&gt;For the next step, I published a &lt;a href="https://github.com/CleanScrape/agent-skills/tree/main/skills/apify-cleanscrape-exhibitor-research" rel="noopener noreferrer"&gt;Map Your Show research skill&lt;/a&gt;. A compatible assistant can use the saved rows to build a sourced shortlist or explain a changes export while keeping different events and incomplete checks separate.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this exhibitor export to shortlist companies mentioning packaging. Keep every booth, show the matching evidence, and leave unknown details blank. Do not run another scrape.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The skill does not find private attendee details or create a schedule. Its instructions are free. New Actor runs and any assistant usage are billed separately.&lt;/p&gt;

</description>
      <category>webscraping</category>
    </item>
  </channel>
</rss>
