<?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: Abinash Sonowal</title>
    <description>The latest articles on DEV Community by Abinash Sonowal (@abinash_sonowal_64176dc95).</description>
    <link>https://dev.to/abinash_sonowal_64176dc95</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%2F4020863%2F36c93c24-8531-4728-a417-a8e53234559c.jpg</url>
      <title>DEV Community: Abinash Sonowal</title>
      <link>https://dev.to/abinash_sonowal_64176dc95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abinash_sonowal_64176dc95"/>
    <language>en</language>
    <item>
      <title>How to Build a Google Shopping Scraper (and why it's so hard)</title>
      <dc:creator>Abinash Sonowal</dc:creator>
      <pubDate>Wed, 08 Jul 2026 08:14:45 +0000</pubDate>
      <link>https://dev.to/abinash_sonowal_64176dc95/how-to-build-a-google-shopping-scraper-and-why-its-so-hard-10hd</link>
      <guid>https://dev.to/abinash_sonowal_64176dc95/how-to-build-a-google-shopping-scraper-and-why-its-so-hard-10hd</guid>
      <description>&lt;p&gt;💻 &lt;strong&gt;&lt;a href="https://github.com/abinashrasonowal/google-shopping" rel="noopener noreferrer"&gt;View the full source code on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🛒 &lt;strong&gt;&lt;a href="https://apify.com/breathtaking_turtle/google-shopping" rel="noopener noreferrer"&gt;Run the Google Shopping Scraper on Apify&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re building an e-commerce price tracker or competitor analysis tool, you’ll quickly realize that scraping individual stores (Amazon, Walmart, Target, etc.) is a nightmare. Every site has a different DOM structure, different anti-bot measures, and different pagination logic. &lt;/p&gt;

&lt;p&gt;The easiest solution? Scrape &lt;strong&gt;Google Shopping&lt;/strong&gt;. It aggregates everything for you. But there’s a catch: scraping Google is incredibly difficult. &lt;/p&gt;

&lt;p&gt;In this post, I'll explain exactly why it's so hard, the underlying code logic required to bypass Google's defenses, and how you can run my pre-built scraper for fractions of a cent.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why is scraping Google Shopping so hard?
&lt;/h2&gt;

&lt;p&gt;If you just run a standard &lt;code&gt;fetch&lt;/code&gt; or &lt;code&gt;axios&lt;/code&gt; request against Google Shopping, you won't get what you expect. Here is what you're up against:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Aggressive Anti-Bot &amp;amp; Captchas:&lt;/strong&gt; Google heavily monitors traffic. If you make too many requests from a single datacenter IP, you will instantly hit a CAPTCHA wall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic DOM &amp;amp; Deferred Execution:&lt;/strong&gt; The HTML that Google returns is not the HTML you see in the browser. Critical product data isn't in standard HTML tags; it is injected dynamically by JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "OAPV" Async Call &amp;amp; Hidden Data:&lt;/strong&gt; Google often loads the most important pricing and variant data via asynchronous internal API calls (like OAPV and &lt;code&gt;batchexecute&lt;/code&gt;) after the page loads. If you don't use a headless browser (which is slow and expensive), you have to reverse-engineer how Google hides this data in the initial HTML payload before the async calls fire.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  The Code Logic: How we beat it (Without a Headless Browser)
&lt;/h2&gt;

&lt;p&gt;To keep costs extremely low ($0.003 per run) and speeds blazing fast (under 10 seconds), I built the &lt;a href="https://apify.com/breathtaking_turtle/google-shopping" rel="noopener noreferrer"&gt;Google Shopping Search Scraper&lt;/a&gt; entirely in Node.js without using Playwright or Puppeteer. &lt;/p&gt;

&lt;p&gt;Here is the exact logic of how it works under the hood:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. SERP Proxies
&lt;/h3&gt;

&lt;p&gt;Instead of standard datacenter proxies, the scraper uses specialized &lt;code&gt;GOOGLE_SERP&lt;/code&gt; proxies provided by Apify. These proxies are designed specifically to rotate IPs optimally and handle Google's fingerprinting, ensuring we rarely hit a block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createProxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GOOGLE_SERP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;countryCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Localized pricing!&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProxyHttpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUrl&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Crafting the Exact Request
&lt;/h3&gt;

&lt;p&gt;We construct the URL targeting &lt;code&gt;tbm=shop&lt;/code&gt; (The Shopping tab). We explicitly pass &lt;code&gt;hl&lt;/code&gt; (language) and &lt;code&gt;gl&lt;/code&gt; (country) parameters so Google returns the correct localized pricing and currency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iphone 16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tbm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://www.google.com/search?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Parsing the Deferred HTML Payload
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. Because we aren't using a browser, the async JS never executes. Instead, we have to extract the data manually from hidden script tags. &lt;/p&gt;

&lt;p&gt;For example, Google defers the loading of real product URLs and images by hiding them inside escaped JavaScript blocks (&lt;code&gt;jsl.dh()&lt;/code&gt;). Our parser uses a custom regex to find these blocks, decodes the JS strings (&lt;code&gt;\xHH&lt;/code&gt;), and loads them into Cheerio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** Parse the deferred HTML hidden inside jsl.dh() blocks */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractInjectedHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;injected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/jsl&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;dh&lt;/span&gt;&lt;span class="se"&gt;\([^&lt;/span&gt;&lt;span class="sr"&gt;,&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+,&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*"&lt;/span&gt;&lt;span class="se"&gt;((?:[^&lt;/span&gt;&lt;span class="sr"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\]&lt;/span&gt;&lt;span class="sr"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sr"&gt;;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Decode \xHH sequences to reconstruct the HTML&lt;/span&gt;
        &lt;span class="nx"&gt;injected&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;decodeJsString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cheerio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;injected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Extracting the &lt;code&gt;google.ldi&lt;/code&gt; Image Map
&lt;/h3&gt;

&lt;p&gt;High-resolution product images are not stored in &lt;code&gt;&amp;lt;img src="..."&amp;gt;&lt;/code&gt; tags. Google stores them in a massive JSON object mapped by IDs (&lt;code&gt;google.ldi&lt;/code&gt;). We parse this object out of the raw HTML and map the image URLs back to the DOM nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ldiMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractLdiMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Parses google.ldi = {...};&lt;/span&gt;
&lt;span class="c1"&gt;// Later, when parsing a product card:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dimg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ldiMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Constructing the Immersive URL
&lt;/h3&gt;

&lt;p&gt;Finally, to get deep pricing (what Google calls the immersive "oshop" view), we have to extract internal Google IDs (&lt;code&gt;headlineOfferDocid&lt;/code&gt;, &lt;code&gt;imageDocid&lt;/code&gt;, &lt;code&gt;catalogid&lt;/code&gt;) from the DOM's &lt;code&gt;data-*&lt;/code&gt; attributes and reconstruct a highly specific &lt;code&gt;prds=&lt;/code&gt; query parameter string.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Assembling the Final Product Object
&lt;/h3&gt;

&lt;p&gt;Once we have bypassed the blocks, extracted the deferred HTML, mapped the high-res images, and constructed the deep immersive URLs, all that is left is to assemble the clean JSON payload that our API consumers expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SELECTORS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;buildProductUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headlineOfferDocid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageDocid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;catalogid&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SELECTORS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;second_hand_condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;extractCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;extractRating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;review_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;extractReviewCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SELECTORS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;injectedImages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;By reverse-engineering Google's deferred JS and async payloads, this scraper can extract ~40 products in under 10 seconds, returning a beautiful, clean JSON array of products, prices, ratings, and URLs.&lt;/p&gt;

&lt;p&gt;If you are building a price monitor or doing market research, don't waste weeks trying to bypass Google's captchas and decipher their injected JS blocks. You can run my actor directly on Apify's infrastructure, or view the full source code yourself!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy Scraping!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webscraping</category>
    </item>
  </channel>
</rss>
