<?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>Turning podcasts into text: a 52-minute NASA episode, 8,022 words, and the bugs real audio found</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sat, 31 Oct 2026 17:41:45 +0000</pubDate>
      <link>https://dev.to/cleanscrape/turning-podcasts-into-text-a-52-minute-nasa-episode-8022-words-and-the-bugs-real-audio-found-56n0</link>
      <guid>https://dev.to/cleanscrape/turning-podcasts-into-text-a-52-minute-nasa-episode-8022-words-and-the-bugs-real-audio-found-56n0</guid>
      <description>&lt;p&gt;A podcast holds a lot of useful information, and almost none of it can be searched, quoted or passed to another tool. So I built a podcast transcription tool on Apify. You paste a feed, an Apple Podcasts link or a link to an audio file, and you get the text back with timestamps and subtitle files.&lt;/p&gt;

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

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

&lt;p&gt;One link is enough. This is the run from the video, an episode of NASA's Houston We Have a Podcast:&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;"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;"https://podcasts.apple.com/us/podcast/the-moon-base/id1262594123?i=1000789048885"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"quality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"accurate"&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;It also accepts an RSS feed, a podcast's website, or a direct link to an MP3, M4A, WAV or MP4 file. Standard quality uses the Whisper base model and Accurate uses Whisper small. Both run inside the Actor, so there's no OpenAI key to bring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The output
&lt;/h2&gt;

&lt;p&gt;The 52:18 episode became 8,022 words in 23 minutes on Accurate. Each row has the show, the title, the date, the length, the detected language, the full text and timestamped segments:&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Moon Base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:52:18"&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;"wordCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8022&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"segments"&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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;80.5&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;"a home for astronauts on another celestial body."&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 also get TXT, SRT and VTT files, so the transcript can go straight onto a video or into a search index.&lt;/p&gt;

&lt;h2&gt;
  
  
  What real audio taught me
&lt;/h2&gt;

&lt;p&gt;The first version passed its tests on short clean clips. Real podcasts found the interesting bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory grows with the audio.&lt;/strong&gt; Whisper's memory use went up by about 55 MB per minute of audio. A 5-minute test looked fine, and a 5-hour file crashed a 4 GB run. The fix was to feed it 5-minute chunks, each cut at the quietest tenth of a second near the boundary so no word gets split. A 5-hour file now peaks at 1.75 GB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first 30 seconds can lie.&lt;/strong&gt; Whisper detects the language from the start of the file. Podcasts often start with an ad, and one Finnish episode opened with an English ad, so the whole episode was transcribed as English. It now takes short samples across the file and lets them vote, weighted by confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The same show, pasted twice, cost double.&lt;/strong&gt; A feed link and an Apple link for one show are different links to the same audio. Episodes already in the run are now skipped, whichever link they came from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real speech costs more than a test sample.&lt;/strong&gt; My first benchmark used a clean narration. Real conversation ran about 25% slower, and Finnish was the slowest of the languages I tried. That changed the price of the Accurate tier before launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following a show
&lt;/h2&gt;

&lt;p&gt;Give a run a watch name and put it on a schedule. The first run takes the newest episode, and each later run transcribes only what has appeared since. A check with nothing new costs $0.003.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it can't do
&lt;/h2&gt;

&lt;p&gt;It doesn't label speakers. It works on one language per file. Some podcast hosts refuse automated downloads: in a test of 134 shows, the newest episode of 127 could be reached. The rest are reported in the run and their audio isn't charged. YouTube, TikTok and Spotify links aren't supported.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/podcast-transcription" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/podcast-transcription&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;$6 per 1,000 audio minutes on Standard and $15 on Accurate, less on paid Apify plans. The episode above cost $0.80. You can export to Excel, CSV or JSON, or call it from your own code or an AI agent through Apify's MCP server.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>An economic calendar built only from official sources: the Fed, ECB, BLS, ONS and more in one table</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Tue, 27 Oct 2026 16:07:47 +0000</pubDate>
      <link>https://dev.to/cleanscrape/an-economic-calendar-built-only-from-official-sources-the-fed-ecb-bls-ons-and-more-in-one-table-3i3k</link>
      <guid>https://dev.to/cleanscrape/an-economic-calendar-built-only-from-official-sources-the-fed-ecb-bls-ons-and-more-in-one-table-3i3k</guid>
      <description>&lt;p&gt;Every number on an economic calendar has a release time set by an official agency: the Bureau of Labor Statistics for CPI and jobs, the BEA for GDP, the Fed and the ECB for rate decisions. Those agencies all publish their schedules openly, but each in its own format: an iCalendar file, a JSON feed, an HTML table, a paged API. So I built a small tool on Apify that reads 13 of those official calendars and returns one clean table.&lt;/p&gt;

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

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

&lt;p&gt;Pick economies and dates. Everything else is optional.&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;"countries"&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;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AU"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dateRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minimumImpact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&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 took 26 seconds and saved 20 releases for 27 October to 2 November 2026. Wednesday had Australia's CPI at 00:30 UTC, the Bank of Canada at 13:45 and the Fed's decision at 18:00. Thursday had US GDP at 12:30 and the ECB at 13:15. The UK had no medium or high impact releases that week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Times you can trust, and when you can't
&lt;/h2&gt;

&lt;p&gt;Every row has the time in UTC and in the agency's local time, plus a status:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;confirmed&lt;/strong&gt;: the agency published the exact time (14 of the 20)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;standard&lt;/strong&gt;: a central bank's usual time, like the ECB's 14:15 Frankfurt time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;provisional&lt;/strong&gt;: a weekly schedule that can shift around holidays (US jobless claims)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;date only&lt;/strong&gt;: the agency publishes the day but not the time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Past releases come with values
&lt;/h2&gt;

&lt;p&gt;For past CPI releases the tool adds the value. US CPI and euro area HICP carry the first published annual rate; the UK, Canada and Australia carry the current official series value. One run over the past year returned 76 inflation releases from all five economies. In the euro area, inflation went from 1.7% in January 2026 to 3.8% in September.&lt;/p&gt;

&lt;p&gt;There are no consensus forecasts: those are compiled privately and are not free to reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following changes
&lt;/h2&gt;

&lt;p&gt;Give the run a watch name and schedule it daily. After the first run, each run returns only what changed: new, moved, cancelled or released events.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/economic-calendar-api" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/economic-calendar-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;$3 per 1,000 events plus half a cent per country checked, less on paid Apify plans. The week above cost $0.08. Export to Excel, CSV or Google Sheets, or call it from your own code or an AI agent through Apify's MCP server.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>api</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Every cut in a 15-minute film: extracting 166 scene frames from a video link</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 25 Oct 2026 14:21:19 +0000</pubDate>
      <link>https://dev.to/cleanscrape/every-cut-in-a-15-minute-film-extracting-166-scene-frames-from-a-video-link-4o66</link>
      <guid>https://dev.to/cleanscrape/every-cut-in-a-15-minute-film-extracting-166-scene-frames-from-a-video-link-4o66</guid>
      <description>&lt;p&gt;If you want to send a video to an AI vision model, build a thumbnail picker, or index a lecture by its slides, you rarely want every frame. You want one frame per shot. So I built a small tool on Apify that takes a video link and returns those frames as images, with their exact times.&lt;/p&gt;

&lt;p&gt;Here is what it does on Sintel, the 14:48 open movie from the Blender Foundation.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The input
&lt;/h2&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;"videos"&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://archive.org/download/Sintel/sintel-2048-stereo.mp4"&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;"scenes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contactSheet"&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;It found &lt;strong&gt;166 shots&lt;/strong&gt; and saved one frame for each. The scan took 3 minutes 22 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it finds the cuts
&lt;/h2&gt;

&lt;p&gt;In this precise mode it compares every frame with the one before. When the picture changes completely, that is a cut, and a frame is saved there. When the camera only pans or zooms, the picture changes a little at a time; that is not counted as a cut. (An earlier version did count fast camera moves, which is how I learned to require a sharp peak rather than a large change.)&lt;/p&gt;

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

&lt;p&gt;Overview mode reads only the keyframes, the full pictures a video file stores every few seconds. On the same film it returned 24 frames in &lt;strong&gt;21 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slides and screen recordings
&lt;/h2&gt;

&lt;p&gt;On a 60-second lecture recording with a moving mouse pointer, precise mode with high sensitivity found all &lt;strong&gt;6 slides&lt;/strong&gt; (at 0:00, 0:10, 0:20, 0:30, 0:40 and 0:50) and ignored the pointer.&lt;/p&gt;

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

&lt;p&gt;Every frame comes with its time, timecode, size and an image link (JPG, PNG or WebP), and every video gets a contact sheet: all its frames on one page. Other modes: a frame every N seconds, a set number of evenly spaced frames, or exact timestamps.&lt;/p&gt;

&lt;p&gt;It reads MP4, MOV, WebM, MKV, AVI, MPEG-TS, OGV and animated GIF from direct links, S3 and other storage links, Dropbox and Google Drive.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/video-frame-extractor" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/video-frame-extractor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;$2 per 1,000 frames, $0.005 per video, and in precise mode $0.01 per minute of 1080p video at 30 fps (smaller videos count less): the 166-frame Sintel run costs about $0.45, the overview run about $0.05. Use it on videos you own or may use.&lt;/p&gt;

&lt;p&gt;Sintel © Blender Foundation, durian.blender.org, CC BY 3.0.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>video</category>
      <category>ai</category>
      <category>automation</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>Which AI companies are hiring engineers, and what they pay: 691 jobs from career pages in 9 seconds</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 25 Oct 2026 14:20:08 +0000</pubDate>
      <link>https://dev.to/cleanscrape/which-ai-companies-are-hiring-engineers-and-what-they-pay-691-jobs-from-career-pages-in-9-seconds-34e4</link>
      <guid>https://dev.to/cleanscrape/which-ai-companies-are-hiring-engineers-and-what-they-pay-691-jobs-from-career-pages-in-9-seconds-34e4</guid>
      <description>&lt;p&gt;Job boards repost, duplicate and keep expired listings. The cleanest source for who is hiring is the company's own careers page, and most companies run it on one of a handful of job board systems: Greenhouse, Lever, Ashby, Workable, Recruitee, Personio or Teamtailor. So I built a small tool on Apify that reads those boards directly.&lt;/p&gt;

&lt;p&gt;Here is one real run: engineering jobs at seven AI companies.&lt;/p&gt;

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

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

&lt;p&gt;You can paste a careers link, the company's website, or just its name. The tool finds the right board and says how it found it, so nothing is guessed.&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;"companies"&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://jobs.ashbyhq.com/openai"&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://job-boards.greenhouse.io/anthropic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"perplexity.ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ElevenLabs"&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://jobs.ashbyhq.com/cohere"&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://jobs.lever.co/mistral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"huggingface.co"&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;"titleKeywords"&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;"engineer"&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;The run took 9 seconds and saved 691 open jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is hiring
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI&lt;/strong&gt;: 356 engineering jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic&lt;/strong&gt;: 209&lt;/li&gt;
&lt;li&gt;Perplexity 46, ElevenLabs 41, Cohere 34, Hugging Face 5&lt;/li&gt;
&lt;li&gt;Mistral's board had no open jobs that day&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What they pay
&lt;/h2&gt;

&lt;p&gt;497 of the 691 jobs publish a yearly salary range in US dollars. Take the middle of each range, and half of them are above &lt;strong&gt;$355,500 a year&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;483 of the jobs (about 7 in 10) are in the United States. The rest are spread across 20 other countries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following hiring over time
&lt;/h2&gt;

&lt;p&gt;Give the run a watch name and schedule it. The first run saves every job as a starting point; after that, each run saves only the jobs that are new, and lists the ones that closed in a separate table.&lt;/p&gt;

&lt;p&gt;I tried it on 25 tech companies with 7,492 open jobs between them. Checked again five hours later (on a Saturday), the next run found 1 new job (a senior engineer at Cloudflare) and 1 that closed (a compliance role at Stripe). Small, but that is the point: a daily check returns only what changed.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/career-site-jobs-scraper" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/career-site-jobs-scraper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;$1 per 1,000 jobs plus $2 per 1,000 companies, less on paid Apify plans: the run above costs about $0.70. Export to Excel, CSV or Google Sheets, or call it from your own code or an AI agent through Apify's MCP server.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>career</category>
      <category>ai</category>
    </item>
    <item>
      <title>Checking casino affiliate pages for 18+ notices and terms, page by page</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Mon, 19 Oct 2026 10:23:50 +0000</pubDate>
      <link>https://dev.to/cleanscrape/checking-casino-affiliate-pages-for-18-notices-and-terms-page-by-page-4hjk</link>
      <guid>https://dev.to/cleanscrape/checking-casino-affiliate-pages-for-18-notices-and-terms-page-by-page-4hjk</guid>
      <description>&lt;p&gt;Casino brands work with hundreds of affiliate and review sites, and each of those pages tells players something about the brand's bonus. Whether a page shows an age notice, links to safer-gambling help and puts the terms next to the offer is something compliance teams check by hand, page by page. I built a small tool on Apify that does the reading: it searches Google from the country you choose, reads every page through a connection in that country, and returns one row per page.&lt;/p&gt;

&lt;p&gt;No casino is named or shown in this video: brands, sites, offers, promo codes and links are blurred. It is about checking pages, not about any offer.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What one run found
&lt;/h2&gt;

&lt;p&gt;The numbers are from one real run on Oct 18 2026 (United Kingdom, one brand): 10 pages on 8 sites, checked in under a minute and a half. Across those pages the brand's offer appeared in 9 different versions. All 5 affiliate pages showed an age notice and linked to safer-gambling help; 4 pages showed the offer with no terms next to it. Pages built with JavaScript are marked, so a notice they show later is not counted as missing. The rows report what each page shows and what is missing from it; they are not a legal verdict, since the rules differ by country and by who a page targets.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it reads a page
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The offer:&lt;/strong&gt; from the title, the main heading, offer cards and comparison tables. In a table that lists several casinos, an offer counts only when it sits in your brand's row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notices:&lt;/strong&gt; age notices (18+, 19+, 21+), safer-gambling links and helplines (BeGambleAware, GamCare, GAMSTOP, 1-800-GAMBLER, ConnexOntario and others), an ad or affiliate disclosure, and wording such as "risk-free".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terms next to the offer:&lt;/strong&gt; T&amp;amp;Cs, wagering, expiry or minimum deposit in the offer's box, or within about 500 characters of the offer's numbers in the page text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Country:&lt;/strong&gt; each page is read from the country being checked; in our tests one page in eight showed a different offer to visitors from another country.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pages it cannot read&lt;/strong&gt; (bot checks, files, JavaScript-only pages) are listed in the run report with the reason, and never charged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The price is $8 per 1,000 saved pages; pages without an offer and pages that could not be read are free.&lt;/p&gt;

&lt;p&gt;Try it: &lt;a href="https://apify.com/cleanscrape/casino-bonus-checker" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/casino-bonus-checker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Maintained by CleanScrape. Questions or a reproducible issue: &lt;a href="mailto:contact.cleanscrape@gmail.com"&gt;contact.cleanscrape@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CleanScrape is independent of Apify and of every casino, affiliate site and network.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>marketing</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Which Kick streamers your competitors sponsor: 26 energy-drink sponsorships from 10,000 live streams</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Mon, 12 Oct 2026 17:15:31 +0000</pubDate>
      <link>https://dev.to/cleanscrape/which-kick-streamers-your-competitors-sponsor-26-energy-drink-sponsorships-from-10000-live-streams-3388</link>
      <guid>https://dev.to/cleanscrape/which-kick-streamers-your-competitors-sponsor-26-energy-drink-sponsorships-from-10000-live-streams-3388</guid>
      <description>&lt;p&gt;Kick streamers advertise their sponsors in plain sight: a chat command in the stream title, a brand link in the channel's link panel, sometimes a promo code. Nobody collects that across channels, so I built a small tool on Apify that does: it scans the live streams on Kick, reads each channel's titles, links and the last month of broadcasts, and returns one row per streamer and brand.&lt;/p&gt;

&lt;p&gt;Here is one real use: an energy-drink brand for gamers checking which streamers its competitors sponsor.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The input
&lt;/h2&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;"brands"&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;"HOLY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"G FUEL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Red Bull"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DZIK"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxLiveStreams"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minViewers"&lt;/span&gt;&lt;span class="p"&gt;:&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="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 run looked through 10,000 live streams, picked the 26 streamers whose live title named one of the brands, and checked each channel in depth. It took about four minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  One row per streamer and brand
&lt;/h2&gt;

&lt;p&gt;Each sponsorship row says where the brand shows up (live title, past broadcast titles, channel links, bio), how many of the streamer's last 30 broadcasts named it, how many hours those were, and any promo or affiliate codes. One example: &lt;strong&gt;rybsonlol&lt;/strong&gt;, live with 20,518 viewers at the time, named HOLY in all 30 recent broadcasts, 276.6 hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The brand summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HOLY&lt;/strong&gt;: 16 streamers, 26,211 live viewers at the time, 357 broadcasts and 2,507 hours in the past month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DZIK&lt;/strong&gt; and &lt;strong&gt;G FUEL&lt;/strong&gt;: 5 streamers each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red Bull&lt;/strong&gt;: none in this scan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A sponsorship here means the channel points viewers to the brand. It is what the channel shows publicly, not a confirmed contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it every day
&lt;/h2&gt;

&lt;p&gt;Give the run a watch name and schedule it. Each row then carries &lt;code&gt;isNew&lt;/code&gt;, so a new sponsorship (a streamer starting with a brand) stands out. Export any table to Excel or CSV.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/kick-sponsor-tracker" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/kick-sponsor-tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About 110 brands are recognised out of the box (drinks, gear, game stores, VPNs, skin sites, sportsbooks and more), and any brand you type is tracked the same way. $3 per 1,000 sponsorships, no start fee: this run cost about $0.18. No login, public data only.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>marketing</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Who sold the most Pokémon cards on Whatnot in a day: two checks of the top 50 sellers</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Mon, 12 Oct 2026 16:00:06 +0000</pubDate>
      <link>https://dev.to/cleanscrape/who-sold-the-most-pokemon-cards-on-whatnot-in-a-day-two-checks-of-the-top-50-sellers-2dh6</link>
      <guid>https://dev.to/cleanscrape/who-sold-the-most-pokemon-cards-on-whatnot-in-a-day-two-checks-of-the-top-50-sellers-2dh6</guid>
      <description>&lt;p&gt;Whatnot ranks its top sellers per category every week, but the leaderboard does not say how much each seller sold or who is growing. I built a small tool on Apify that saves the top sellers with their lifetime items sold, followers, rating and rank, and compares every run with the one before.&lt;/p&gt;

&lt;p&gt;Here is one real use: the top 50 Pokémon card sellers, checked twice, a day apart.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The input
&lt;/h2&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;"categories"&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;"Pokémon Cards"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"topSellers"&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;"historyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Daily check"&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 history name ties runs together: each run is compared with the last run under the same name. The first run, on Oct 11 at 14:51 UTC, saved the 50 sellers as a starting point. The second, 24.5 hours later, saved them again in 15 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in a day
&lt;/h2&gt;

&lt;p&gt;Each row of the second run has the change since the first: items sold since the last check, sales per day, new followers and the rank change.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The 48 sellers in the top 50 on both days sold &lt;strong&gt;41,380 items&lt;/strong&gt; between the checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;outsidehits&lt;/strong&gt; sold 2,633 items, gained 1,447 followers and moved from #13 to #10.&lt;/li&gt;
&lt;li&gt;The biggest climber, &lt;strong&gt;pokeynpulls&lt;/strong&gt;, went from #23 to #16.&lt;/li&gt;
&lt;li&gt;Two sellers are new in the top 50.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Items sold come from Whatnot's own lifetime count on each profile, so "sold since the last check" is simply the difference between two checks. Whatnot can show the count a little late for sellers who are live, which is why a daily schedule works better than an hourly one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it every day
&lt;/h2&gt;

&lt;p&gt;Save the input as a task and schedule it daily. Every run adds a day of sales, followers and rank for each seller, and the "Changes since last check" view shows only the columns that moved. Export any view to Excel or CSV.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/whatnot-seller-tracker" rel="noopener noreferrer"&gt;https://apify.com/cleanscrape/whatnot-seller-tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;$3 per 1,000 sellers, no start fee: a daily check of 50 sellers costs about $0.15. No login, public data only.&lt;/p&gt;

&lt;p&gt;Niko, CleanScrape developer&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>python</category>
      <category>pokemon</category>
    </item>
    <item>
      <title>What a PSA 10 Charizard costs on Whatnot, from 73 live listings</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Sun, 11 Oct 2026 15:43:20 +0000</pubDate>
      <link>https://dev.to/cleanscrape/what-a-psa-10-charizard-costs-on-whatnot-from-73-live-listings-3dl2</link>
      <guid>https://dev.to/cleanscrape/what-a-psa-10-charizard-costs-on-whatnot-from-73-live-listings-3dl2</guid>
      <description>&lt;p&gt;Whatnot is the live shopping marketplace where a lot of trading cards, sneakers and collectibles change hands, often during live streams. It has no public API for listings, so I built a small tool on Apify that turns a Whatnot search into a table, with the seller's track record on every row.&lt;/p&gt;

&lt;p&gt;Here is one real use: what does a PSA 10 Charizard cost on Whatnot right now, and who is selling them?&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The search
&lt;/h2&gt;

&lt;p&gt;The input works like the filters on the website: a keyword, a category, and Whatnot's own card filters.&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;"searchQueries"&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;"charizard"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&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;"Pokémon Cards"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gradedOnly"&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;"gradingServices"&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;"PSA"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"grades"&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;"10"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"buyFormat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"buy_it_now"&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;"price_asc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResultsPerSearch"&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;The run returned 73 listings in 16 seconds. Each row has the price, currency, quantity, category, the date it was listed and a link, plus the seller's items sold on Whatnot, followers, rating and number of reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prices
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Listings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Under $100&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$100 to $499&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$500 to $1,999&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$2,000 and up&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The cheapest was $15 and the most expensive $490,000, a 1999 first edition. One more listing asked $999,999, a placeholder price rather than a real offer, so I left it out of the table. The middle listing of all 73 was $300 ($292.50 without the placeholder).&lt;/p&gt;

&lt;p&gt;Two things to keep in mind. These are asking prices: Whatnot shows sold prices only to logged-in users, and the tool never logs in. And "PSA 10" is a filter on how sellers tag their listings, so a few titles mention other grades. Read the titles before you compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is selling
&lt;/h2&gt;

&lt;p&gt;The seller columns are what make this more than a price list. The cheapest PSA 10 Charizard from a seller rated 5.0 with over a thousand sales was $100, from a seller with 11,846 items sold. In Python, with the Apify client:&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;statistics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;median&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_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;cleanscrape/whatnot-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchQueries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;charizard&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;categories&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;Pokémon Cards&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;gradedOnly&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;gradingServices&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;PSA&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;grades&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;10&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;buyFormat&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;buy_it_now&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;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;price_asc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxResultsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;rows&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;real&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;999999&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;rows&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;listings, median&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;trusted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerRating&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;5&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerSoldCount&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&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;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trusted&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;r&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;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerUsername&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerSoldCount&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;
  
  
  Live shows
&lt;/h2&gt;

&lt;p&gt;Switch "What to find" to live and upcoming shows and the same category gives you the streams. The top 100 live Pokémon card shows had 6,041 viewers between them when I ran it, the biggest over a thousand. Each show row has the title, viewers, start time, format (52 Singles, 29 Surprise Sets and 19 Breaks in this run), tags and seller, and you can ask for the items for sale in each show too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Only new listings
&lt;/h2&gt;

&lt;p&gt;For deal alerts, sort by "Newly listed", turn on "Only listings or shows not saved before" and schedule the task. Each run looks at the newest listings and returns the ones earlier runs did not save, plus price drops on ones they did. The skipped ones are not charged.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/whatnot-scraper" rel="noopener noreferrer"&gt;Whatnot Scraper on Apify&lt;/a&gt;. You pay per listing saved, and the search above cost about $0.15. It works on all eight Whatnot marketplaces: the US, Canada, the UK, Germany, France, Belgium, the Netherlands and Australia.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>webscraping</category>
      <category>python</category>
      <category>pokemon</category>
    </item>
    <item>
      <title>What a data analyst earns in New York, Chicago and Austin, from 150 Google Jobs listings</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Wed, 07 Oct 2026 18:31:59 +0000</pubDate>
      <link>https://dev.to/cleanscrape/what-a-data-analyst-earns-in-new-york-chicago-and-austin-from-150-google-jobs-listings-48ke</link>
      <guid>https://dev.to/cleanscrape/what-a-data-analyst-earns-in-new-york-chicago-and-austin-from-150-google-jobs-listings-48ke</guid>
      <description>&lt;p&gt;Google Jobs is the job search built into Google. It pulls listings from LinkedIn, Indeed, Glassdoor, company career sites and local job boards into one place, which makes it a good single source when you want to compare jobs across cities. It has no public API, so I built a small tool on Apify that turns a Google Jobs search into a table.&lt;/p&gt;

&lt;p&gt;Here is one real use: I wanted to see what data analyst jobs pay in New York, Chicago and Austin.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The search
&lt;/h2&gt;

&lt;p&gt;The input is a job title and a list of locations. Every title is searched in every location:&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;"data analyst"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"locations"&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;"New York, NY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chicago, IL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Austin, TX"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxJobsPerSearch"&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;The run returned 150 jobs in 43 seconds. Most came via LinkedIn (34), Indeed (16), Dice (8) and Monster (8); the rest from company career sites and smaller boards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salaries as numbers
&lt;/h2&gt;

&lt;p&gt;Google shows pay as text, such as "$124K–$177K a year" or "$57.70–$62.50 an hour". The tool splits that into &lt;code&gt;salaryMin&lt;/code&gt;, &lt;code&gt;salaryMax&lt;/code&gt;, &lt;code&gt;salaryCurrency&lt;/code&gt; and &lt;code&gt;salaryPeriod&lt;/code&gt;, so you can sort and filter without parsing anything yourself.&lt;/p&gt;

&lt;p&gt;64 of the 150 jobs listed a salary. Taking the midpoint of each yearly range and the median per city:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;City&lt;/th&gt;
&lt;th&gt;Jobs with a yearly salary&lt;/th&gt;
&lt;th&gt;Median of range midpoints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New York&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;$106,734&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chicago&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;$97,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;$110,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are small samples from one search on October 6, 2026, not a salary survey. Austin coming out on top surprised me; with 13 jobs it can easily move by the next run.&lt;/p&gt;

&lt;p&gt;In Python, with the Apify client:&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;statistics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;median&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_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;cleanscrape/google-jobs-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data analyst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;locations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York, NY&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;Chicago, IL&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;Austin, TX&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;maxJobsPerSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;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;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York, NY&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;Chicago, IL&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;Austin, TX&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;mids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryMin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryMax&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;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchLocation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryPeriod&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;year&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&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;mids&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mids&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;mids&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More than 10 jobs per search
&lt;/h2&gt;

&lt;p&gt;Google Jobs shows 10 jobs per search. To get more, the tool runs close variations of the same search (posted today, this week, full time, remote, senior and so on) and keeps each job once. A search stops when the variations stop finding new jobs, so a narrow search ends early instead of paying for repeats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Only new jobs
&lt;/h2&gt;

&lt;p&gt;For job alerts, turn on "Only jobs not saved before" and schedule the task. Each run returns only jobs earlier runs did not save, and the skipped ones are not charged.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apify.com/cleanscrape/google-jobs-scraper" rel="noopener noreferrer"&gt;Google Jobs Scraper on Apify&lt;/a&gt;. You pay per job saved: $2.95 per 1,000 jobs since October 21, 2026, less on paid Apify plans. At that price the 150-job run above costs about $0.44. It works in 36 countries; outside English-speaking ones, type the job title in the local language.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>jobs</category>
      <category>webscraping</category>
      <category>python</category>
    </item>
    <item>
      <title>What Chinese viewers say about coffee, second by second</title>
      <dc:creator>CleanScrape</dc:creator>
      <pubDate>Tue, 06 Oct 2026 05:50:02 +0000</pubDate>
      <link>https://dev.to/cleanscrape/what-chinese-viewers-say-about-coffee-second-by-second-1gb8</link>
      <guid>https://dev.to/cleanscrape/what-chinese-viewers-say-about-coffee-second-by-second-1gb8</guid>
      <description>&lt;p&gt;If you want to know what Chinese viewers watch and say about a topic, Bilibili is one of the best places to look. It is one of China's biggest video sites, and its viewers comment in two ways: ordinary comments under the video, and danmaku, the comments that fly across the video at the moment they were written.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://apify.com/cleanscrape/bilibili-scraper" rel="noopener noreferrer"&gt;CleanScrape's Bilibili Scraper&lt;/a&gt; to get both into a spreadsheet without a Bilibili account. I'm the developer, so this is a walkthrough of my own tool, not an independent review. Every number in it was checked against my runs.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  One search term, 100 videos
&lt;/h2&gt;

&lt;p&gt;For the example I searched for 咖啡 (coffee) and turned on top comments and danmaku. You need an Apify account to run the Actor, but no Bilibili login or cookies. 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;"searchQueries"&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;"咖啡"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxVideosPerQuery"&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;"includeComments"&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;"includeDanmaku"&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;"maxDanmakuPerVideo"&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 run took 81 seconds and saved 100 videos with views, likes, coins, favorites, shares and tags, plus 1,357 top comments and replies and 12,055 danmaku. Videos, comments, danmaku and creators each land in their own table, so an export holds one kind of row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it doesn't get blocked
&lt;/h2&gt;

&lt;p&gt;Bilibili limits how fast one visitor can read each kind of data, and it blocks an IP for minutes to an hour when that limit is crossed. I measured those limits field by field before building the Actor. It spreads the work over several proxy connections at once (nine in this run), keeps each one under the measured pace, and moves work elsewhere when Bilibili refuses a request. In this run, 5 of 604 requests were refused, all for danmaku, and every one was retried on another connection. No video is missing its danmaku.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the danmaku show
&lt;/h2&gt;

&lt;p&gt;The most-watched video in the results, about drinking six cups of coffee a day, has 5,108,457 views and 63,604 coins. A second run collected the 1,800 danmaku Bilibili's player loads for it (10,343 were sent in total), each with its time in the video.&lt;/p&gt;

&lt;p&gt;Count them in 20-second steps and the busiest stretch after the opening is 0:40 to 1:00, with 136 danmaku. 21 of those are about bitterness, and the running joke is that life is more bitter than coffee:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;再苦能有生活苦: "Can it be more bitter than life?"&lt;/li&gt;
&lt;li&gt;咖啡没有我的命苦: "Coffee isn't as bitter as my life"&lt;/li&gt;
&lt;li&gt;因为生活比咖啡还苦: "Because life is even more bitter than coffee"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That kind of moment-by-moment reaction is hard to get any other way. Comments tell you what people thought after watching; danmaku tell you what they felt at a given second.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top comments
&lt;/h2&gt;

&lt;p&gt;Without login Bilibili shows the top comments of a video (usually 3) and the first 20 replies under each, so this is a sample, not every comment. On the coffee video, the pinned top comment asks whether anyone has managed to quit coffee. It has 5,941 likes and 714 replies.&lt;/p&gt;

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

&lt;p&gt;Open &lt;strong&gt;Storage &amp;gt; Dataset&lt;/strong&gt;, choose Default (videos), Comments, Danmaku or Creators, and download CSV, Excel or JSON. From the API, the run object lists the four datasets under &lt;code&gt;storageIds.datasets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At base prices a video costs $1.49 per 1,000, a comment $0.49 per 1,000 and a danmaku $0.10 per 1,000, with no start fee and platform usage included. 100 videos with tags cost about $0.15. There are also ready-made examples for &lt;a href="https://apify.com/cleanscrape/bilibili-scraper/examples/bilibili-videos-for-a-keyword" rel="noopener noreferrer"&gt;a keyword&lt;/a&gt;, &lt;a href="https://apify.com/cleanscrape/bilibili-scraper/examples/bilibili-video-danmaku-export" rel="noopener noreferrer"&gt;one video's danmaku&lt;/a&gt; and &lt;a href="https://apify.com/cleanscrape/bilibili-scraper/examples/bilibili-creator-profile-and-videos" rel="noopener noreferrer"&gt;a creator's profile and videos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Besides search terms, you can paste video links, BV ids, creator links or UIDs, or the whole text the Bilibili app copies with Share &amp;gt; Copy link.&lt;/p&gt;

&lt;p&gt;What it can't do without login: every comment of a video, a creator's full upload history (it uses their public collections and series), subtitles, and bilibili.tv, the international site.&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 Bilibili and Apify.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <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 and RSS Feed Reader&lt;/a&gt; partly for this. I'm the developer, so this is a walkthrough of my own tool, not an independent review. Every number in it was checked against my 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 scripts using its unofficial endpoints can encounter &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; for scripts using the common &lt;code&gt;TrendReq&lt;/code&gt; methods. It returns pandas 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. The output below is from a real run.&lt;/p&gt;

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

&lt;p&gt;Google offers an &lt;a href="https://developers.google.com/search/apis/trends" rel="noopener noreferrer"&gt;official Trends API alpha&lt;/a&gt;, with access by application. pytrends does not use that API. 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. Limits vary by traffic and connection; neither this wrapper nor a proxy can guarantee that requests will never be rate-limited.&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;The method calls stay the same. One optional line, &lt;code&gt;fetch&lt;/code&gt;, gets several data types in one run:&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;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;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 plaintext"&gt;&lt;code&gt;                                 query  value
0      toasted coconut cream cold brew  19700
1           smores cold brew starbucks  19700
4    how to make cold brew concentrate   2050
&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>
  </channel>
</rss>
