<?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: TrendCraft</title>
    <description>The latest articles on DEV Community by TrendCraft (@kazm_cemz_7f4650563415).</description>
    <link>https://dev.to/kazm_cemz_7f4650563415</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%2F4199198%2F037d3cb7-ce0c-490c-a76c-806a80789ad2.png</url>
      <title>DEV Community: TrendCraft</title>
      <link>https://dev.to/kazm_cemz_7f4650563415</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kazm_cemz_7f4650563415"/>
    <language>en</language>
    <item>
      <title>Eventbrite's search API is gone. Here's how to get Eventbrite, Meetup and Luma events in one list</title>
      <dc:creator>TrendCraft</dc:creator>
      <pubDate>Wed, 21 Oct 2026 21:53:50 +0000</pubDate>
      <link>https://dev.to/kazm_cemz_7f4650563415/eventbrites-search-api-is-gone-heres-how-to-get-eventbrite-meetup-and-luma-events-in-one-list-33j8</link>
      <guid>https://dev.to/kazm_cemz_7f4650563415/eventbrites-search-api-is-gone-heres-how-to-get-eventbrite-meetup-and-luma-events-in-one-list-33j8</guid>
      <description>&lt;p&gt;If you have tried to build anything with event data, you probably found this out the hard way: &lt;strong&gt;Eventbrite shut down its public event search endpoint (&lt;code&gt;/v3/events/search&lt;/code&gt;) back in 2020.&lt;/strong&gt; You can still read events you organize, but you can't search "all tech events in London next month" anymore.&lt;/p&gt;

&lt;p&gt;Meetup moved to a GraphQL API that needs an OAuth app, and Luma, where a lot of AI and startup events live now, has no public search API at all.&lt;/p&gt;

&lt;p&gt;So if you want a simple list of upcoming events in a city, you're stuck stitching three very different sites together. This post shows a shortcut, and then one fun thing to build with it: &lt;strong&gt;a weekly local events newsletter written by AI.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Get events from all three sites in one run
&lt;/h2&gt;

&lt;p&gt;I'll use the &lt;a href="https://apify.com/trendcraft/events-scraper" rel="noopener noreferrer"&gt;Eventbrite, Meetup &amp;amp; Luma Events Scraper&lt;/a&gt; on Apify. Disclosure: I built it, for exactly this problem. No API keys or logins needed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/trendcraft/events-scraper" rel="noopener noreferrer"&gt;Actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. The free Apify plan includes $5 of monthly credit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; a city, e.g. &lt;code&gt;London&lt;/code&gt;, &lt;code&gt;Berlin&lt;/code&gt;, &lt;code&gt;San Francisco&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keywords&lt;/strong&gt; (optional): &lt;code&gt;AI&lt;/code&gt;, &lt;code&gt;startup&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;design&lt;/code&gt;...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From date / To date&lt;/strong&gt; (optional): e.g. the next 7 days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sources:&lt;/strong&gt; keep all three, or pick some.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max events per source:&lt;/strong&gt; e.g. &lt;code&gt;50&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or as JSON 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;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"London"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sources"&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;"eventbrite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"luma"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"meetup"&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-11-01"&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-11-07"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResultsPerSource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every event comes back in &lt;strong&gt;the same format&lt;/strong&gt;, whichever site it came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;startDate&lt;/code&gt;, &lt;code&gt;endDate&lt;/code&gt;, &lt;code&gt;timezone&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;venueName&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;city&lt;/code&gt;, &lt;code&gt;country&lt;/code&gt;, &lt;code&gt;latitude&lt;/code&gt;, &lt;code&gt;longitude&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isOnline&lt;/code&gt;, &lt;code&gt;isFree&lt;/code&gt;, &lt;code&gt;priceMin&lt;/code&gt;, &lt;code&gt;priceMax&lt;/code&gt;, &lt;code&gt;currency&lt;/code&gt;, &lt;code&gt;soldOut&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;organizerName&lt;/code&gt;, &lt;code&gt;organizerUrl&lt;/code&gt;, &lt;code&gt;attendeeCount&lt;/code&gt;, &lt;code&gt;categories&lt;/code&gt;, &lt;code&gt;imageUrl&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fields a site doesn't publish are &lt;code&gt;null&lt;/code&gt; (Luma's public feed has no description, Eventbrite doesn't show attendee counts). Download as CSV, Excel or JSON from the &lt;strong&gt;Output&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;There's also an &lt;strong&gt;Online events only&lt;/strong&gt; switch (Eventbrite and Meetup) if you want virtual events instead of a city.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Turn it into a weekly newsletter with AI
&lt;/h2&gt;

&lt;p&gt;Here is the whole thing in Python: fetch next week's events, then ask an AI model to write a short newsletter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

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

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trendcraft/events-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&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;AI&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;startDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;endDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxResultsPerSource&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;startDate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;venueName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Online&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isFree&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a short, friendly weekly newsletter of AI events in London. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pick the 10 most interesting, group them by day, one sentence each, keep the links. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Only use events from this list:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# paste into Claude or ChatGPT, or call their API here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a schedule (on the Actor: &lt;strong&gt;Actions → Save as a new task&lt;/strong&gt;, then &lt;strong&gt;Schedules&lt;/strong&gt;), and you have the data side of a newsletter that refreshes itself every week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other things people use it for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lead lists:&lt;/strong&gt; organizers of recurring events are potential customers for venues, sponsors, catering and event tools. &lt;code&gt;organizerName&lt;/code&gt; and &lt;code&gt;organizerUrl&lt;/code&gt; give you the starting point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;City calendars and apps:&lt;/strong&gt; one feed instead of three integrations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market research:&lt;/strong&gt; what topics are growing in a city, how many events are free vs paid, typical ticket prices.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;You pay per event saved; the current price is on the Actor's &lt;strong&gt;Pricing&lt;/strong&gt; tab. At the time of writing it is $5 per 1,000 events, so a weekly 100-event newsletter costs about $2 a month, inside the free monthly credit.&lt;/p&gt;

&lt;p&gt;Good to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eventbrite and Meetup rank keyword results by meaning, so a few results may not contain the exact word. Luma matches words in titles and host names.&lt;/li&gt;
&lt;li&gt;Luma shows events nearest to your location; the radius setting applies to Luma and Meetup.&lt;/li&gt;
&lt;li&gt;Only public event information is collected.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Missing a site or a field? Open an issue on the Actor's &lt;strong&gt;Issues&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was drafted with AI assistance; input names and output fields were checked against the Actor itself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>python</category>
      <category>tutorial</category>
      <category>ai</category>
    </item>
    <item>
      <title>Find your competitor's weak spots: export App Store and Google Play reviews and let AI sort the complaints</title>
      <dc:creator>TrendCraft</dc:creator>
      <pubDate>Wed, 21 Oct 2026 21:50:50 +0000</pubDate>
      <link>https://dev.to/kazm_cemz_7f4650563415/find-your-competitors-weak-spots-export-app-store-and-google-play-reviews-and-let-ai-sort-the-5hl4</link>
      <guid>https://dev.to/kazm_cemz_7f4650563415/find-your-competitors-weak-spots-export-app-store-and-google-play-reviews-and-let-ai-sort-the-5hl4</guid>
      <description>&lt;p&gt;Before you build an app, the most useful research is free and public: &lt;strong&gt;what people hate about the apps that already exist.&lt;/strong&gt; It sits in the 1- and 2-star reviews on the App Store and Google Play.&lt;/p&gt;

&lt;p&gt;The problem is getting it out. The stores show a few reviews at a time, Apple and Google format them differently, and copy-pasting 2,000 reviews into a chat window is not a plan.&lt;/p&gt;

&lt;p&gt;This post shows a simple workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export reviews from &lt;strong&gt;both stores&lt;/strong&gt; into one CSV (no code needed).&lt;/li&gt;
&lt;li&gt;Give the CSV to an AI model and get back a &lt;strong&gt;ranked list of complaints and feature requests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Turn that into a short list of product ideas you can actually test.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Export the reviews
&lt;/h2&gt;

&lt;p&gt;I'll use the &lt;a href="https://apify.com/trendcraft/app-reviews-scraper" rel="noopener noreferrer"&gt;App Store &amp;amp; Google Play Reviews Scraper&lt;/a&gt; on Apify. Disclosure: I built it. It takes App Store and Google Play links side by side and returns the same fields for both, which is what makes the AI step easy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/trendcraft/app-reviews-scraper" rel="noopener noreferrer"&gt;Actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. The free Apify plan includes $5 of monthly credit.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Apps&lt;/strong&gt;, paste the store links of the app you want to study, for example both versions of a habit tracker:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://apps.apple.com/us/app/.../id1234567890&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://play.google.com/store/apps/details?id=com.example.app&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Plain IDs work too (&lt;code&gt;1234567890&lt;/code&gt;, &lt;code&gt;com.example.app&lt;/code&gt;).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Countries&lt;/strong&gt;, add one or more markets: &lt;code&gt;us&lt;/code&gt;, &lt;code&gt;gb&lt;/code&gt;, &lt;code&gt;de&lt;/code&gt;... Reviews are collected separately for each country.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Max reviews per app and country&lt;/strong&gt;, for example &lt;code&gt;500&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Sort by&lt;/strong&gt; to &lt;code&gt;newest&lt;/code&gt; to see what people complain about &lt;em&gt;now&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;, then download the result as &lt;strong&gt;CSV&lt;/strong&gt; from the &lt;strong&gt;Output&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every row looks the same, whichever store it came from:&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;"googlePlay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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="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;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Keeps logging me out after the last update..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date"&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-10-19T14:18:56"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2026.279"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"thumbsUpCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;rating&lt;/code&gt;, &lt;code&gt;appVersion&lt;/code&gt; and &lt;code&gt;thumbsUpCount&lt;/code&gt; are the useful columns: you can filter to low ratings, see which version broke something, and weight complaints by how many people agreed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limits to know:&lt;/strong&gt; Apple only shares the latest 500 reviews per app, country and sort order. To get more from the App Store, add countries or run both sort orders. Google Play has no fixed limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Keep only the complaints
&lt;/h2&gt;

&lt;p&gt;You don't need 5-star "great app!!" reviews for this. In Google Sheets or Excel, filter &lt;code&gt;rating&lt;/code&gt; to &lt;strong&gt;1, 2 and 3&lt;/strong&gt;. For a popular app, that's usually a few hundred rows, small enough for any AI chat.&lt;/p&gt;

&lt;p&gt;Or in Python:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dataset.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rating&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thumbsUpCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bad&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;store&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;rating&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;appVersion&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;thumbsUpCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complaints.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complaints saved&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;h2&gt;
  
  
  Step 3: Let AI sort them
&lt;/h2&gt;

&lt;p&gt;Upload &lt;code&gt;complaints.csv&lt;/code&gt; to Claude or ChatGPT and use a prompt like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;These are 1-3 star reviews of [APP NAME] from the App Store and Google Play.
1. Group them into themes (bugs, pricing, missing features, UX, support...).
2. For each theme give: number of reviews, total thumbsUpCount, and 2 short quotes.
3. Rank themes by how painful and how common they are.
4. List the top 5 feature requests people explicitly ask for.
5. Note any theme that started after a specific appVersion.
Be concrete. Do not invent reviews that are not in the file.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you get back is a ranked map of the competitor's weak spots, with real quotes as evidence. The "started after version X" question often finds the best opportunities: users who were happy until an update broke something are actively looking for an alternative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Turn it into ideas
&lt;/h2&gt;

&lt;p&gt;A few patterns that come up again and again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"I'd pay for it if..."&lt;/strong&gt; reviews are direct pricing research.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The same missing feature across several competitors&lt;/strong&gt; is a niche worth testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complaints only from one country&lt;/strong&gt; (language, payment methods, local content) can mean a local version is wanted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Used to be great"&lt;/strong&gt; reviews tell you which features users actually valued.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the same export for 3-5 competing apps and compare the themes side by side. That's an afternoon of work instead of weeks of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing it in code
&lt;/h2&gt;

&lt;p&gt;The official &lt;code&gt;apify-client&lt;/code&gt; package runs the same scraper from Python:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trendcraft/app-reviews-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;389801252&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;com.instagram.android&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;countries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxReviewsPerApp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;newest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviews&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;h2&gt;
  
  
  Cost, and when you don't need this
&lt;/h2&gt;

&lt;p&gt;Results are priced per review; the current price is on the Actor's &lt;strong&gt;Pricing&lt;/strong&gt; tab. At the time of writing it is $0.25 per 1,000 reviews, so a 2,000-review study costs about fifty cents.&lt;/p&gt;

&lt;p&gt;If you only need Google Play reviews and are comfortable with Python, the free &lt;code&gt;google-play-scraper&lt;/code&gt; library works well. The Actor is useful when you want &lt;strong&gt;both stores in one format&lt;/strong&gt;, several countries in one run, a scheduled daily export, or no code at all.&lt;/p&gt;




&lt;p&gt;Questions or a missing field? Open an issue on the Actor's &lt;strong&gt;Issues&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was drafted with AI assistance; input names and output fields were checked against the Actor itself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>ai</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Send Google Trends data to Google Sheets every morning (no pytrends, no 429 errors)</title>
      <dc:creator>TrendCraft</dc:creator>
      <pubDate>Wed, 21 Oct 2026 21:44:28 +0000</pubDate>
      <link>https://dev.to/kazm_cemz_7f4650563415/send-google-trends-data-to-google-sheets-every-morning-no-pytrends-no-429-errors-k9d</link>
      <guid>https://dev.to/kazm_cemz_7f4650563415/send-google-trends-data-to-google-sheets-every-morning-no-pytrends-no-429-errors-k9d</guid>
      <description>&lt;p&gt;If you have ever tried to pull Google Trends data with code, you probably know this message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytrends.exceptions.TooManyRequestsError: The request failed: Google returned a response with code 429
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;pytrends&lt;/strong&gt;, the library almost everyone used, was archived on GitHub in April 2025. Nobody ships fixes anymore, and Google rate-limits it quickly: it works for a while, then the 429s start.&lt;/p&gt;

&lt;p&gt;Most articles stop at "pytrends is dead, here are some alternatives". This one solves one concrete job instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Every morning, put fresh Google Trends numbers for my keywords — plus today's trending searches in my country — into a Google Sheet.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No server, no cron job, no proxy management. Then I'll show the same thing in 10 lines of Python for people who prefer code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we will build
&lt;/h2&gt;

&lt;p&gt;A Google Sheet that refreshes itself daily with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interest over time&lt;/strong&gt; (0–100) for your keywords, for example &lt;code&gt;chatgpt&lt;/code&gt;, &lt;code&gt;claude&lt;/code&gt;, &lt;code&gt;gemini&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rising related queries&lt;/strong&gt; — the "Breakout" searches you want to catch early&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Today's trending searches&lt;/strong&gt; in a country, with traffic estimates and news links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll use the &lt;a href="https://apify.com/trendcraft/google-trends-scraper" rel="noopener noreferrer"&gt;Google Trends Scraper&lt;/a&gt; on Apify. Disclosure: I built it, because I needed exactly this and got tired of babysitting 429 errors. It handles retries and rotating IPs, and it only charges for results it actually returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Run it once
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://apify.com/trendcraft/google-trends-scraper" rel="noopener noreferrer"&gt;Actor page&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. The free Apify plan includes $5 of monthly credit, which is enough for this whole tutorial.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Search terms&lt;/strong&gt;, add your keywords (up to 5 per comparison group).&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Compare terms on one chart&lt;/strong&gt; if you want them on the same 0–100 scale, like on the Trends website.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Country / region code&lt;/strong&gt; (e.g. &lt;code&gt;US&lt;/code&gt;, &lt;code&gt;GB&lt;/code&gt;, &lt;code&gt;DE&lt;/code&gt;) and &lt;strong&gt;Time range&lt;/strong&gt; (e.g. &lt;code&gt;Past 30 days&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Trending now: countries&lt;/strong&gt;, add &lt;code&gt;US&lt;/code&gt; (or any country) to also get today's trending searches.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a few seconds you get items like this:&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"search"&lt;/span&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="s2"&gt;"gemini"&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;"interestOverTime"&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;span class="nl"&gt;"date"&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-10-19T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"values"&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="nl"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"claude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"gemini"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;38&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;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"relatedQueries"&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="nl"&gt;"gemini"&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="nl"&gt;"rising"&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="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini argon 4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Breakout"&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;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;You can download this as CSV or Excel straight from the &lt;strong&gt;Output&lt;/strong&gt; tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Schedule it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Actions → Save as a new task&lt;/strong&gt;, so your keywords and settings are saved.&lt;/li&gt;
&lt;li&gt;On the task page, open &lt;strong&gt;Schedules&lt;/strong&gt; and create a schedule, for example every day at 07:00.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From now on it runs every morning by itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Send results to Google Sheets
&lt;/h2&gt;

&lt;p&gt;On the task, open the &lt;strong&gt;Integrations&lt;/strong&gt; tab and add the &lt;strong&gt;Google Sheets&lt;/strong&gt; integration. Connect your Google account, choose a spreadsheet and map the output. After each scheduled run, the new rows land in your sheet.&lt;/p&gt;

&lt;p&gt;That's it: a self-updating trends dashboard, without writing or hosting any code. From there it's easy to add a chart in Sheets, or let Zapier, Make or n8n post the "Breakout" queries to Slack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Python version (10 lines)
&lt;/h2&gt;

&lt;p&gt;If you'd rather stay in code, the official &lt;code&gt;apify-client&lt;/code&gt; package runs the same scraper and gives you the results. Get your API token from &lt;strong&gt;Apify Console → Settings → API &amp;amp; Integrations&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





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

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

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trendcraft/google-trends-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchTerms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chatgpt&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;claude&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;gemini&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;compareTerms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;geo&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;US&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;timeframe&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;today 1-m&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;trendingNowGeos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;latest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interestOverTime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;values&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# trendingNow
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approxTraffic&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;Load it into pandas with &lt;code&gt;pd.DataFrame(...)&lt;/code&gt; and you're back to the workflow you had with pytrends, minus the 429s.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you don't need this
&lt;/h2&gt;

&lt;p&gt;To be honest: if you only check a handful of keywords now and then, a free library may be enough. &lt;strong&gt;trendspy&lt;/strong&gt; and &lt;strong&gt;trendspyg&lt;/strong&gt; are maintained alternatives to pytrends and are worth trying first.&lt;/p&gt;

&lt;p&gt;A hosted scraper makes sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the job has to run &lt;strong&gt;every day without failing&lt;/strong&gt; (reports, dashboards, alerts),&lt;/li&gt;
&lt;li&gt;you track &lt;strong&gt;hundreds of keywords&lt;/strong&gt;, so rate limits hit you constantly,&lt;/li&gt;
&lt;li&gt;you want results in &lt;strong&gt;Sheets, Zapier, Make or n8n&lt;/strong&gt; without running a server.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;You pay per result: one result per keyword (or per comparison group of up to 5 keywords) and one per trending search. Current pricing is on the Actor's &lt;strong&gt;Pricing&lt;/strong&gt; tab. Example: a daily run with 5 compared keywords (1 result) plus one country's trending list (about 20 results) is roughly 630 results a month, which is about $3 at $5 per 1,000 results, so it fits inside the free $5 monthly credit. Skip the trending list and it drops to cents.&lt;/p&gt;




&lt;p&gt;If you try it and something breaks, or you need a field that isn't there, open an issue on the Actor's &lt;strong&gt;Issues&lt;/strong&gt; tab. I read them all.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was drafted with AI assistance; input names and output fields were checked against the Actor itself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>seo</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
