<?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: MikeL</title>
    <description>The latest articles on DEV Community by MikeL (@detectzestack).</description>
    <link>https://dev.to/detectzestack</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%2F2107035%2Fe0c68bde-32d6-4613-b96c-c6abfa4280b1.png</url>
      <title>DEV Community: MikeL</title>
      <link>https://dev.to/detectzestack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/detectzestack"/>
    <language>en</language>
    <item>
      <title>How to Detect Typekit (Adobe Fonts) on Any Website (2026)</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Fri, 24 Jul 2026 14:01:20 +0000</pubDate>
      <link>https://dev.to/detectzestack/how-to-detect-typekit-adobe-fonts-on-any-website-2026-58o6</link>
      <guid>https://dev.to/detectzestack/how-to-detect-typekit-adobe-fonts-on-any-website-2026-58o6</guid>
      <description>&lt;p&gt;Typekit has not officially existed since 2018, and yet it is still one of the most-detected font technologies on the web. That is because when Adobe rebranded the service to Adobe Fonts, the serving infrastructure kept its old hostnames: every site using it today still loads a stylesheet from &lt;code&gt;use.typekit.net&lt;/code&gt;, exactly as it did a decade ago. Those hostnames are the detection signature, and they are impossible to hide.&lt;/p&gt;

&lt;p&gt;This guide covers how to detect Typekit by hand in under a minute, why the manual approach stops working the moment you have a list of domains instead of one, and how to do the same check programmatically with the DetectZeStack API. Every response shown below comes from the live API against a real site.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Typekit (and Why It's Now Adobe Fonts)
&lt;/h2&gt;

&lt;p&gt;Typekit launched in 2009 as a subscription library of licensed web fonts, was acquired by Adobe in 2011, and was folded into Creative Cloud as Adobe Fonts in 2018. The product name changed; the plumbing did not. Web projects are still identified by a short kit ID, stylesheets are still served from &lt;code&gt;use.typekit.net&lt;/code&gt;, and the legacy JavaScript loader still lives on &lt;code&gt;use.typekit.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That continuity has a practical consequence for anyone doing technology detection: &lt;strong&gt;Typekit and Adobe Fonts are the same signal.&lt;/strong&gt; Fingerprint databases carry both names because both eras of the product left embeds in the wild, and both fingerprints match the same hostnames. Scan a site with a live embed and you will get two results describing one integration. This is expected, and we will see it in a real API response below.&lt;/p&gt;

&lt;p&gt;The signal is also worth detecting. Adobe Fonts rides on a paid Creative Cloud subscription, so unlike a free font CDN, its presence tells you the company behind the site pays for typography. If you want to turn that into a prospect list rather than a yes/no check, see &lt;a href="https://detectzestack.com/blog/find-companies-using-adobe-fonts" rel="noopener noreferrer"&gt;how to find companies using Adobe Fonts&lt;/a&gt;, which applies this detection to sales prospecting end to end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual Ways to Detect Typekit on a Website
&lt;/h2&gt;

&lt;p&gt;For a single site you already have open in a browser, three manual checks settle the question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check for use.typekit.net Script and Stylesheet URLs
&lt;/h3&gt;

&lt;p&gt;View the page source (&lt;code&gt;Ctrl+U&lt;/code&gt; in most browsers) and search for &lt;code&gt;typekit&lt;/code&gt;. The modern embed is a stylesheet link in the head:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://use.typekit.net/abc1def.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Older integrations use the JavaScript embed instead: a script served from &lt;code&gt;use.typekit.com&lt;/code&gt; plus a load call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://use.typekit.com/abc1def.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Typekit&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="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either one is conclusive. No technology other than Adobe's font service loads assets from those hosts, which is why automated detection assigns this signature full confidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Look for the Kit ID and wf-loading Body Classes
&lt;/h3&gt;

&lt;p&gt;The short lowercase token in the embed URL, the &lt;code&gt;abc1def&lt;/code&gt; above, is the kit ID. Adobe generates one per web project, and it identifies which licensed fonts the page may load. It is visible to anyone, but it is domain-scoped on Adobe's side, so seeing it does not let a third party reuse the fonts.&lt;/p&gt;

&lt;p&gt;Sites using the JavaScript embed give you a second, runtime clue. The loader stamps state classes on the &lt;code&gt;html&lt;/code&gt; or &lt;code&gt;body&lt;/code&gt; element while fonts load: &lt;code&gt;wf-loading&lt;/code&gt; while requests are in flight, then &lt;code&gt;wf-active&lt;/code&gt; on success or &lt;code&gt;wf-inactive&lt;/code&gt; on failure. Open the browser console and check:&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;
&lt;span class="c1"&gt;// "wf-typekit-active wf-active ..." on a Typekit JS-embed site&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the limitation: these classes are added by JavaScript at runtime, so they only exist after the page executes its scripts, and only with the JS embed. The stylesheet embed, which is what Adobe generates for new projects, produces no &lt;code&gt;wf-*&lt;/code&gt; classes at all. Treat their absence as meaningless and their presence as supporting evidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect Network Requests to p.typekit.net
&lt;/h3&gt;

&lt;p&gt;The third check is the network tab. Open developer tools, reload the page, and filter requests by &lt;code&gt;typekit&lt;/code&gt;. A site with a live integration shows the kit CSS from &lt;code&gt;use.typekit.net&lt;/code&gt; and then the actual font files from &lt;code&gt;p.typekit.net&lt;/code&gt;, Adobe's font-serving host. You can do the same from the console without watching the waterfall:&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;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getEntriesByType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resource&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&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;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typekit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that returns URLs, the fonts are not just referenced, they are being served. This distinguishes a live integration from a leftover embed pointing at a deleted kit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Manual Detection Breaks at Scale
&lt;/h2&gt;

&lt;p&gt;All three checks above take under a minute for one site. They stop being viable the moment the question changes from "does this site use Typekit?" to "which of these 500 domains use Typekit?" Manual checking at that scale fails in predictable ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not batch.&lt;/strong&gt; Thirty seconds per site is over four hours of tab-switching for 500 domains, with no machine-readable output at the end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is inconsistent.&lt;/strong&gt; A human checker misses the JS embed on one site, forgets the network tab on another, and mistakes a dead kit for a live one on a third. A fingerprint engine applies the same rules to every domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It captures nothing else.&lt;/strong&gt; While you are in the page source looking for one string, the site's CMS, analytics stack, and CDN are sitting in the same HTML unrecorded. An API scan returns all of it in one pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It does not repeat.&lt;/strong&gt; Technology lists go stale. Rescanning a list monthly by hand is not a workflow anyone sustains; rerunning a script is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fix is to move the same signatures into an API call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detect Typekit With the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;DetectZeStack detects Typekit server-side from the HTML a site returns: a &lt;code&gt;link&lt;/code&gt; tag pointing at &lt;code&gt;use.typekit.net&lt;/code&gt; or &lt;code&gt;use.typekit.com&lt;/code&gt;, or a script sourced from &lt;code&gt;use.typekit.com&lt;/code&gt;. Both patterns resolve at a &lt;code&gt;confidence&lt;/code&gt; of &lt;code&gt;100&lt;/code&gt;, and because they sit in the raw HTML, no headless browser is involved.&lt;/p&gt;

&lt;p&gt;Try it first with no API key. The &lt;code&gt;/demo&lt;/code&gt; endpoint is free and needs no signup; Behance, Adobe's own portfolio network, is a convenient live example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=behance.net"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "Typekit")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which returns:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typekit"&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="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"Font scripts"&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;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typekit is an online service which offers a subscription library of fonts."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://typekit.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typekit.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;source&lt;/code&gt; field is &lt;code&gt;http&lt;/code&gt;, meaning the detection came from the page HTML. That is the only place Typekit can appear: fonts load from Adobe's domain rather than the customer's, so there is no DNS record or TLS artifact to key on. If a site answers a scan with an error page instead of its real HTML, the embed is invisible and the detection cannot fire, which is why checking &lt;code&gt;meta.status_code&lt;/code&gt; matters, covered below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Domain Check With /analyze
&lt;/h3&gt;

&lt;p&gt;The demo endpoint is rate limited and meant for spot checks. For real use, get a free API key from &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;RapidAPI&lt;/a&gt; and call &lt;code&gt;/analyze&lt;/code&gt;, which returns the full stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=behance.net"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"url"&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://www.behance.net/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"www.behance.net"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Adobe Fonts"&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;"Font scripts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typekit"&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;"Font scripts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vue.js"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Varnish"&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;"Caching"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HSTS"&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;"Security"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTP/3"&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;"Miscellaneous"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Let's Encrypt"&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;"SSL/TLS certificate authority"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tls"&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;"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="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Font scripts"&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;"Adobe Fonts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typekit"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"JavaScript frameworks"&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;"Vue.js"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Caching"&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;"Varnish"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Security"&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;"HSTS"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Miscellaneous"&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;"HTTP/3"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"SSL/TLS certificate authority"&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;"Let's Encrypt"&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;"meta"&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tech_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scan_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4415&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;There is the double entry promised earlier: &lt;code&gt;Typekit&lt;/code&gt; and &lt;code&gt;Adobe Fonts&lt;/code&gt;, both under &lt;strong&gt;Font scripts&lt;/strong&gt;, both matched by the same &lt;code&gt;use.typekit.net&lt;/code&gt; embed. Filter on either name, or on the category, and do not count them as two technologies. The &lt;code&gt;categories&lt;/code&gt; object makes the category route a single key lookup: &lt;code&gt;.categories["Font scripts"]&lt;/code&gt; answers "does this site use a hosted font service?" without walking the array.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check meta.status_code before trusting an absence. Typekit is detected only from the returned HTML. A site that answers your scan with a 403 or 429 shows no embed even if it uses the service, and the scan does not fail loudly; it just comes back thinner. Treat a non-200 status as inconclusive, not as a negative.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Results are cached for 24 hours by default; a repeat scan of the same domain returns &lt;code&gt;"cached": true&lt;/code&gt; with a much lower &lt;code&gt;response_ms&lt;/code&gt;. That is worth knowing when benchmarking: the second scan measures the cache, not the scanner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scanning Many Domains With POST /analyze/batch
&lt;/h3&gt;

&lt;p&gt;Batch is how you work through a list. It accepts up to 10 URLs per request and scans them concurrently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["behance.net", "example.com", "stripe.com"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result.technologies[]?.name == "Typekit")
| .result.domain'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response wraps one result per URL with a per-item &lt;code&gt;error&lt;/code&gt; field, so one unreachable domain does not fail the batch, and the &lt;code&gt;jq&lt;/code&gt; filter prints only the domains where Typekit was found. Each URL counts as one request against your monthly quota; batching saves round trips, not quota. For working through lists in the hundreds or thousands, &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;how to batch scan 1,000 websites&lt;/a&gt; covers chunking, retries, and rate pacing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typekit vs Google Fonts vs Self-Hosted Fonts: Telling Them Apart
&lt;/h2&gt;

&lt;p&gt;Font loading comes in three flavors, and each leaves a different trail:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;th&gt;What it implies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Typekit / Adobe Fonts&lt;/td&gt;
&lt;td&gt;Stylesheet or script from use.typekit.net / use.typekit.com; fonts from p.typekit.net&lt;/td&gt;
&lt;td&gt;Paid Creative Cloud subscription; licensed typefaces; an active design budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Fonts&lt;/td&gt;
&lt;td&gt;Stylesheet from fonts.googleapis.com; fonts from fonts.gstatic.com&lt;/td&gt;
&lt;td&gt;Free hosted fonts; a typeface choice, but no spend signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;@font-face rules pointing at the site's own domain; no third-party font hosts&lt;/td&gt;
&lt;td&gt;Performance or privacy priorities, or a licensed font served under its own terms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both hosted services land in the &lt;strong&gt;Font scripts&lt;/strong&gt; category (Google's entry is named &lt;code&gt;Google Font API&lt;/code&gt;), so a category filter catches either while a name filter isolates the paid signal. Self-hosted fonts, by design, have no third-party host to fingerprint; their absence from a scan is not a detection failure but the actual answer. The same host-based logic powers detection of other asset CDNs; &lt;a href="https://detectzestack.com/blog/how-to-detect-cdnjs" rel="noopener noreferrer"&gt;detecting cdnjs&lt;/a&gt; is the same pattern applied to JavaScript libraries, and &lt;a href="https://detectzestack.com/blog/how-to-detect-google-tag-manager" rel="noopener noreferrer"&gt;detecting Google Tag Manager&lt;/a&gt; applies it to the tag-management layer of the same pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Your API Key and Start Detecting
&lt;/h2&gt;

&lt;p&gt;The free plan covers 100 requests per month with no credit card, which is enough to confirm the signal on the sites you care about; paid plans start at $9 for 1,000 requests. Every plan returns the same full response: Typekit alongside the CMS, analytics, CDN, and everything else in the stack, in one call.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spot-check a site with &lt;code&gt;/demo&lt;/code&gt;, no key required.&lt;/li&gt;
&lt;li&gt;Get a free key at &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;RapidAPI&lt;/a&gt; and move to &lt;code&gt;/analyze&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Feed your domain list through &lt;code&gt;/analyze/batch&lt;/code&gt;, 10 URLs at a time.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Typekit is one of the easiest technologies on the web to detect because it cannot be consumed without advertising itself: the embed sits in the HTML, the hostnames never changed through a rebrand, and there is no false-positive path, since nothing else loads assets from Adobe's font hosts. Check one site by searching the source for &lt;code&gt;use.typekit.net&lt;/code&gt;; check five hundred with an API call that applies the same signature uniformly and hands you the rest of the stack for free. Just remember the two quirks: the API returns both Typekit and Adobe Fonts for one integration, and a non-200 &lt;code&gt;status_code&lt;/code&gt; means inconclusive, not absent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-adobe-fonts" rel="noopener noreferrer"&gt;How to Find Companies Using Adobe Fonts&lt;/a&gt; — Turning this detection into a design-budget prospect list&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-google-tag-manager" rel="noopener noreferrer"&gt;How to Detect Google Tag Manager&lt;/a&gt; — The same host-signature approach on the tag-management layer&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-cdnjs" rel="noopener noreferrer"&gt;How to Detect cdnjs&lt;/a&gt; — Detecting asset CDNs by the hosts they load from&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-font-awesome" rel="noopener noreferrer"&gt;How to Detect Font Awesome on Any Website&lt;/a&gt; — The icon-font side of web typography, and why a CSS-only install is the common false negative&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites&lt;/a&gt; — Scaling the batch endpoint past a handful of domains&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Find Companies Using imagesLoaded: API Guide (2026)</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Thu, 16 Jul 2026 14:01:15 +0000</pubDate>
      <link>https://dev.to/detectzestack/find-companies-using-imagesloaded-api-guide-2026-43ld</link>
      <guid>https://dev.to/detectzestack/find-companies-using-imagesloaded-api-guide-2026-43ld</guid>
      <description>&lt;p&gt;imagesLoaded is a small JavaScript library by David DeSandro that answers one question: have the images inside a container finished loading? That sounds too narrow to be a prospecting signal, and that narrowness is exactly why it is a good one. Nobody adds imagesLoaded on a whim. It appears on sites with image-heavy layouts that break without it, and it almost always arrives as part of a specific, dateable front-end stack: jQuery, a masonry-style grid, a WordPress theme or page builder doing the enqueueing.&lt;/p&gt;

&lt;p&gt;This guide shows how imagesLoaded is detected from the outside and how to turn that detection into a prospect list with the DetectZeStack API. The worked example is a live site, and every response shape below comes from the live API.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is imagesLoaded and Why Track Sites That Use It
&lt;/h2&gt;

&lt;p&gt;Browsers report an element's dimensions as zero until its images arrive. Any layout that positions items based on their rendered height — a masonry wall, a justified photo grid, an infinite-scroll feed — will compute positions from those zero heights and paint overlapping bricks unless something waits for the images first. imagesLoaded is that something. It watches a container, fires a callback when every image has loaded or errored, and lets the layout engine run against real dimensions.&lt;/p&gt;

&lt;p&gt;As a technographic signal, that tells you three things about a site before you ever open it. First, the site is visually driven: portfolios, photography, real estate, media, ecommerce catalogs. Second, its layout is computed in JavaScript rather than in modern CSS, which dates the front end — CSS grid and aspect-ratio have made much of this machinery unnecessary. Third, someone assembled this stack deliberately, usually via a WordPress theme, a page builder, or a hand-rolled gallery, and that assembly is now a maintenance surface.&lt;/p&gt;

&lt;h3&gt;
  
  
  How imagesLoaded Fits Into a Front-End Stack (Masonry, Isotope, jQuery Galleries)
&lt;/h3&gt;

&lt;p&gt;imagesLoaded rarely travels alone. It is the companion utility for the same author's layout libraries — Masonry, Isotope, Packery, Flickity — and for jQuery gallery and carousel plugins that need to measure images before arranging them. The canonical pattern looks like this:&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="c1"&gt;// wait for images, then lay out the grid&lt;/span&gt;
&lt;span class="nf"&gt;imagesLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.grid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Masonry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.grid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;itemSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.grid-item&lt;/span&gt;&lt;span class="dl"&gt;'&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;p&gt;The other common delivery vehicle is WordPress itself. WordPress core ships imagesLoaded in &lt;code&gt;wp-includes/js/imagesloaded.min.js&lt;/code&gt;, and themes and page-builder plugins enqueue it whenever a masonry block, filterable portfolio, or gallery widget needs it. That is worth knowing because it shapes what a detection means: a large share of imagesLoaded sites are WordPress sites, and the scan that finds the library will usually name the theme's ecosystem — Elementor, Slick, jQuery — in the same response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Buys From Companies Using imagesLoaded
&lt;/h2&gt;

&lt;p&gt;A company running imagesLoaded has an image-heavy site built on a JavaScript-layout stack that is, in 2026, at least one generation old. Two groups sell into exactly that profile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agencies and Freelancers Selling Front-End Modernization
&lt;/h3&gt;

&lt;p&gt;imagesLoaded is a proxy for the whole jQuery-era gallery stack. A site loading it as a standalone file is very likely also loading jQuery, a carousel plugin, and a theme's worth of layout scripts — the exact surface an agency pitches to replace with modern CSS, a component framework, or a lighter theme. The signal also implies the site owner cares how the site looks: they picked an image-forward design and paid someone to build it once, which makes "your gallery stack is five years old and costing you Core Web Vitals" a pitch aimed at someone who already values the outcome. Because the detection usually arrives with the CMS and page builder attached, the outreach can be specific: you are not guessing that they run WordPress with Elementor, the scan said so.&lt;/p&gt;

&lt;h3&gt;
  
  
  SaaS Vendors Replacing Custom Gallery and Layout Code
&lt;/h3&gt;

&lt;p&gt;Every imagesLoaded detection marks a site that solved image loading and layout by hand. That is the displacement target for gallery and portfolio plugins, digital asset management tools, image CDNs and optimization services, and headless media platforms. The pitch writes itself from the stack: a photography studio gluing imagesLoaded to Masonry inside a WordPress theme is maintaining code that a managed gallery product makes obsolete. And because imagesLoaded correlates with pages that ship many large images, image-optimization vendors get a second angle — these are precisely the sites where LCP improvements are visible to the owner.&lt;/p&gt;

&lt;h2&gt;
  
  
  How DetectZeStack Detects imagesLoaded
&lt;/h2&gt;

&lt;p&gt;DetectZeStack analyzes the HTML a server returns; it does not execute JavaScript. For imagesLoaded that is enough, because the sites worth finding load it as a named file the scanner can see.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script Signatures and CDN Fingerprints
&lt;/h3&gt;

&lt;p&gt;The fingerprint keys on the script source. A script tag whose &lt;code&gt;src&lt;/code&gt; ends in &lt;code&gt;imagesloaded.js&lt;/code&gt; or &lt;code&gt;imagesloaded.min.js&lt;/code&gt; resolves the site to imagesLoaded with a confidence of 100, whether the file is served from the site's own origin, from &lt;code&gt;wp-includes/js/&lt;/code&gt;, or from a public CDN. The signature also captures the version from a &lt;code&gt;?v=&lt;/code&gt; or &lt;code&gt;?ver=&lt;/code&gt; query string when one is present:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/wp-content/plugins/.../imagesloaded.min.js?ver=3.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;?ver=&lt;/code&gt; pattern is how WordPress enqueues every bundled script, which is why imagesLoaded detections so often come with a version number attached and a WordPress detection in the same scan. The version matters for qualification: it is the version of the library the theme shipped, and an old one is a direct measure of how long the front end has gone untouched.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The blind spot to know about: a site that compiles imagesLoaded into a webpack or similar bundle never exposes the filename, so no external scanner can see it — the library's own documentation site bundles its assets and scans clean. In practice this filters your list in a useful direction: script-source detection surfaces exactly the sites loading it the old way, as a standalone file, which are the modernization prospects anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  API Example: Check a Single Domain for imagesLoaded
&lt;/h2&gt;

&lt;p&gt;Confirm the signal by hand first. The &lt;code&gt;/demo&lt;/code&gt; endpoint needs no API key and no signup. Here it is against &lt;code&gt;wpastra.com&lt;/code&gt;, the site of the Astra WordPress theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=wpastra.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "imagesLoaded")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which returns:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"imagesLoaded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&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="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"JavaScript libraries"&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;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jQuery plugin for seeing if the images are loaded."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://imagesloaded.desandro.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&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;Three fields matter. &lt;code&gt;confidence&lt;/code&gt; is &lt;code&gt;100&lt;/code&gt; because the script source matched exactly. &lt;code&gt;version&lt;/code&gt; is &lt;code&gt;3.0.0&lt;/code&gt;, captured from the &lt;code&gt;?ver=&lt;/code&gt; query string on the enqueue. &lt;code&gt;source&lt;/code&gt; is &lt;code&gt;http&lt;/code&gt;, meaning the detection came from the HTML response rather than a DNS or TLS signal. The same scan returned the rest of the story: WordPress, Elementor, Slick, jQuery, and jQuery Migrate — the full image-heavy WordPress stack this article has been describing, in one call.&lt;/p&gt;

&lt;p&gt;For real volume, get a free API key from &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;RapidAPI&lt;/a&gt; and use the authenticated endpoints. When you only need a yes or no, &lt;code&gt;/check&lt;/code&gt; returns one directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/check?url=wpastra.com&amp;amp;tech=imagesLoaded"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wpastra.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"imagesLoaded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"detected"&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;"confidence"&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&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;"JavaScript libraries"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;431&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;tech&lt;/code&gt; parameter is case insensitive, so &lt;code&gt;tech=imagesloaded&lt;/code&gt; works and the response echoes the canonical name &lt;code&gt;imagesLoaded&lt;/code&gt;. When the library is absent, &lt;code&gt;detected&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; and &lt;code&gt;confidence&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;. When a site loads the file without a version query string, &lt;code&gt;version&lt;/code&gt; comes back as an empty string; that is a normal detection, not a partial one.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Example: Build a List of Companies Using imagesLoaded
&lt;/h2&gt;

&lt;p&gt;Single checks answer "does this domain run it?" and require you to bring the domain. The next two endpoints build lists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using /lookup?tech=imagesLoaded with Pagination and Tier Caps
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/lookup&lt;/code&gt; inverts the question: it returns domains already in DetectZeStack's scan index that were observed running imagesLoaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/lookup?tech=imagesLoaded&amp;amp;limit=50"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"technology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"imagesLoaded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"results"&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;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wpastra.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JavaScript libraries"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"first_seen"&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-07-14"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"last_seen"&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-07-14"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"limit"&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;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;first_seen&lt;/code&gt; and &lt;code&gt;last_seen&lt;/code&gt; have no equivalent in a live scan: they tell you when the index first observed the library on that domain and when it was last confirmed. Page through results with &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt;. The rows returned per request are capped by plan, and requesting more than your cap clamps to it rather than erroring:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Max /lookup rows per request&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic (free)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro ($9/mo)&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultra ($29/mo)&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mega ($79/mo)&lt;/td&gt;
&lt;td&gt;800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;/lookup&lt;/code&gt; reflects what has already been scanned, so treat it as a warm start rather than a census of the web. For a niche library like imagesLoaded, the stronger play is the other direction: bring your own candidate domains and scan them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scaling Up with POST /analyze/batch for Your Own Domain Lists
&lt;/h3&gt;

&lt;p&gt;Batch accepts up to &lt;strong&gt;10 URLs per request&lt;/strong&gt; and scans them concurrently. Feed it a directory of photography studios, a list of agencies' portfolio clients, or an export from any lead database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["wpastra.com", "thisiscolossal.com", "example.com"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result.technologies[]?.name == "imagesLoaded")
| .result.domain'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response wraps one result per URL with a per-item &lt;code&gt;error&lt;/code&gt; field, so a single unreachable domain does not fail the batch, and the top level reports &lt;code&gt;total_ms&lt;/code&gt;, &lt;code&gt;successful&lt;/code&gt;, and &lt;code&gt;failed&lt;/code&gt; counts. Each URL in a batch counts as one request against your monthly quota — a 10-URL batch costs 10 requests. Batching saves round trips, not quota.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning Detections Into a Prospect List
&lt;/h2&gt;

&lt;p&gt;Putting it together: read domains from a file, scan them in batches of 10, keep the imagesLoaded sites, and record the stack context that makes the outreach specific.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://detectzestack.p.rapidapi.com/analyze/batch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;HEADERS&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;X-RapidAPI-Key&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;YOUR_KEY&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;X-RapidAPI-Host&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;detectzestack.p.rapidapi.com&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# API maximum per request
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Scan up to 10 domains, yielding (domain, technologies, status_code).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&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;urls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;result&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  skipped &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&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;no result&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="n"&gt;techs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technologies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;techs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domains.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;domains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&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;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

&lt;span class="n"&gt;prospects&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;BATCH_SIZE&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Scanning &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of &lt;/span&gt;&lt;span class="si"&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;domains&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="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;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;techs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&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;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;# The page never loaded, so script tags could not be seen.
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: status &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, inconclusive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;techs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imagesLoaded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;techs&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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;imagesLoaded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;prospects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imagesloaded_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version&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="p"&gt;),&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wordpress&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;yes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WordPress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no&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;jquery&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;yes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jQuery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no&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;stack&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;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: imagesLoaded &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(no version)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imagesloaded_prospects.csv&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;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;fieldnames&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;domain&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;imagesloaded_version&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;wordpress&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;jquery&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;stack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prospects&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&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;prospects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; imagesLoaded sites out of &lt;/span&gt;&lt;span class="si"&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;domains&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; domains.&lt;/span&gt;&lt;span class="sh"&gt;"&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details in that script carry most of the value. The &lt;code&gt;status != 200&lt;/code&gt; guard treats blocked or failed fetches as inconclusive instead of negative — a site behind aggressive bot protection returns no HTML, so the library will be absent from results even if the site runs it, and silently dropping those rows corrupts the list. And the script records the version and the surrounding stack, because "you are running imagesLoaded 3.x inside an Elementor theme with jQuery Migrate" is an opener that proves you looked, where "I noticed you have a website" is not.&lt;/p&gt;

&lt;p&gt;Results are cached for 24 hours by default. A cache hit comes back with &lt;code&gt;"cached": true&lt;/code&gt;, which is worth knowing when you rescan a list: the second pass measures the cache, not the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;imagesLoaded is a narrow library with a broad implication: an image-heavy site whose layout still depends on jQuery-era JavaScript, usually inside a WordPress theme that names itself in the same scan. One API call finds the library, its version, and the entire stack around it — which is the research a modernization pitch or a gallery-SaaS displacement pitch actually needs.&lt;/p&gt;

&lt;p&gt;Start with &lt;code&gt;/demo&lt;/code&gt; to confirm the signal on a site you know. Move to &lt;code&gt;/check&lt;/code&gt; for booleans, &lt;code&gt;/analyze/batch&lt;/code&gt; for your own lists, and &lt;code&gt;/lookup&lt;/code&gt; for a warm start from the index.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-jquery" rel="noopener noreferrer"&gt;How to Detect jQuery on Any Website&lt;/a&gt; — The library imagesLoaded grew up inside, and the anchor of the same legacy stack&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-slick" rel="noopener noreferrer"&gt;How to Detect Slick on Any Website&lt;/a&gt; — The carousel that shows up next to imagesLoaded on the same scans&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-jsdelivr" rel="noopener noreferrer"&gt;Find Companies Using jsDelivr&lt;/a&gt; — One of the CDNs that serves imagesLoaded as a standalone, detectable file&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-cdnjs" rel="noopener noreferrer"&gt;How to Detect cdnjs on Any Website&lt;/a&gt; — The other major library-delivery CDN, detected from the page HTML the same way&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-elementor" rel="noopener noreferrer"&gt;Find Companies Using Elementor&lt;/a&gt; — The page builder that enqueues imagesLoaded for its gallery widgets&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites&lt;/a&gt; — Scaling the batch endpoint past a handful of domains&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt; — Automating prospect qualification end to end&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/tech-stack-enrichment-for-sales-teams" rel="noopener noreferrer"&gt;Tech Stack Enrichment for Sales Teams&lt;/a&gt; — Pushing technographic data into your CRM&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Find Companies Using WP Engine (API Guide 2026)</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Wed, 08 Jul 2026 14:00:55 +0000</pubDate>
      <link>https://dev.to/detectzestack/how-to-find-companies-using-wp-engine-api-guide-2026-hjj</link>
      <guid>https://dev.to/detectzestack/how-to-find-companies-using-wp-engine-api-guide-2026-hjj</guid>
      <description>&lt;p&gt;WP Engine is the managed WordPress host that companies graduate to when their site becomes revenue-critical. Its plans start well above commodity shared hosting, so “uses WP Engine” is one of the rare technographic signals that encodes budget as well as technology: it tells you the company runs WordPress, cares enough about that site to pay a premium for it, and has already delegated the hosting layer to a vendor.&lt;/p&gt;

&lt;p&gt;This guide covers what a WP Engine detection tells you about a company, the exact DNS CNAME and HTTP header signals that reveal the platform, and how to turn a raw domain list into a WP Engine-confirmed lead list with the DetectZeStack API—starting with a single curl command you can run right now, no API key required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Find Companies Using WP Engine?
&lt;/h2&gt;

&lt;p&gt;Technographic data—what technology a company actually runs—often qualifies a prospect better than firmographics alone. A WP Engine detection is a specific, verifiable fact about a company’s infrastructure, and it feeds two distinct workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sales Prospecting for WordPress Agencies and Plugin Vendors
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It confirms WordPress with budget attached.&lt;/strong&gt; Every WP Engine customer runs WordPress—the platform hosts nothing else—and pays managed-hosting prices to do it. If you sell WordPress plugins, themes, maintenance retainers, performance audits, or agency services, a WP Engine list is a WordPress list pre-filtered for willingness to spend on the site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It maps the buyer.&lt;/strong&gt; A company on managed hosting has already decided not to run its own servers. The conversation is with a marketing or web team that owns the site as a business asset, not with an infrastructure team—which changes both the pitch and the pain points: plugin conflicts, page speed, redesigns, content workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It stacks with other filters.&lt;/strong&gt; WP Engine alone is a solid segment; WP Engine plus a page builder or a marketing tool detection is a sharp one. Because a tech detection API returns the whole stack in one response, intersecting filters costs nothing extra—the same trick our &lt;a href="https://detectzestack.com/blog/find-companies-using-elementor" rel="noopener noreferrer"&gt;Elementor prospecting guide&lt;/a&gt; uses at the plugin layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Competitive and Migration Intelligence
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hosting-switch campaigns.&lt;/strong&gt; If you sell a competing platform or migration services, a WP Engine-confirmed list is your total addressable market, enumerated. Rescanning the same list on a schedule shows who has left the platform—and who just arrived.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market sizing.&lt;/strong&gt; Scanning a vertical for managed WordPress adoption shows how seriously that segment treats its web presence, and how the managed-hosting share shifts over time between WP Engine, Kinsta, Pantheon, Flywheel, and the rest—all of which are detectable from the same DNS layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How WP Engine Reveals Itself (Detection Signals)
&lt;/h2&gt;

&lt;p&gt;WP Engine shows up in two independent layers: the DNS records that route traffic to the platform, and the HTTP headers its cache tier stamps on every response. A site that hides one layer frequently gives away the other.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DNS CNAME&lt;/td&gt;
&lt;td&gt;*.wpengine.com&lt;/td&gt;
&lt;td&gt;The domain points at a classic WP Engine install hostname&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS CNAME&lt;/td&gt;
&lt;td&gt;*.wpenginepowered.com&lt;/td&gt;
&lt;td&gt;The newer install hostname pattern (e.g. wp.wpenginepowered.com)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS CNAME&lt;/td&gt;
&lt;td&gt;*.wpeproxy.com&lt;/td&gt;
&lt;td&gt;The domain routes through WP Engine’s proxy network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP header&lt;/td&gt;
&lt;td&gt;X-Powered-By: WP Engine&lt;/td&gt;
&lt;td&gt;The response was served by the WP Engine platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP header&lt;/td&gt;
&lt;td&gt;WPE-Backend: ...&lt;/td&gt;
&lt;td&gt;WP Engine’s cache tier names the backend that produced the response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP header&lt;/td&gt;
&lt;td&gt;X-Pass-Why / X-WPE-Loopback-Upstream-Addr&lt;/td&gt;
&lt;td&gt;Cache-diagnostic headers unique to WP Engine’s stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  DNS CNAME Records Pointing to *.wpengine.com
&lt;/h3&gt;

&lt;p&gt;Every WP Engine install gets a platform hostname, and custom domains reach it through DNS. The classic pattern is a CNAME to &lt;code&gt;&amp;lt;install&amp;gt;.wpengine.com&lt;/code&gt;; newer installs use &lt;code&gt;&amp;lt;install&amp;gt;.wpenginepowered.com&lt;/code&gt;, and traffic routed through the platform’s proxy network resolves through &lt;code&gt;*.wpeproxy.com&lt;/code&gt; hostnames. A single &lt;code&gt;dig&lt;/code&gt; shows it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig www.example.com CNAME +short
examplesite.wpengine.com.

&lt;span class="nv"&gt;$ &lt;/span&gt;dig www.another-example.com CNAME +short
wp.wpenginepowered.com.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three suffixes are unambiguous—no one CNAMEs to a WP Engine hostname without being a customer. DetectZeStack matches all of them and follows the full CNAME chain to find them, since a domain often resolves through a vanity or CDN host first. For the mechanics of chain resolution, see &lt;a href="https://detectzestack.com/blog/dns-based-technology-detection" rel="noopener noreferrer"&gt;DNS-Based Technology Detection&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  WP Engine Cache Headers and Server Fingerprints
&lt;/h3&gt;

&lt;p&gt;WP Engine fronts every install with its own caching and proxy tier, and that tier writes identifiable headers into responses. The clearest is &lt;code&gt;X-Powered-By: WP Engine&lt;/code&gt;; alongside it the platform emits &lt;code&gt;WPE-Backend&lt;/code&gt; (naming the backend that produced the response) and cache diagnostics like &lt;code&gt;X-Pass-Why&lt;/code&gt; and &lt;code&gt;X-WPE-Loopback-Upstream-Addr&lt;/code&gt;. One &lt;code&gt;curl -I&lt;/code&gt; surfaces them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://www.example.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"x-powered-by|wpe|x-pass"&lt;/span&gt;
X-Powered-By: WP Engine
WPE-Backend: apache
X-Pass-Why:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any one of these headers confirms the platform. They are also the reason a WP Engine detection doubles as a WordPress detection: the platform hosts WordPress exclusively, so the header implies the CMS even on sites that have stripped every conventional WordPress fingerprint—a useful backdoor when the methods in &lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;our WordPress detection guide&lt;/a&gt; come up empty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Header Checks Alone Miss Hardened Sites
&lt;/h3&gt;

&lt;p&gt;Neither layer is complete on its own. A CDN or security proxy in front of WP Engine can strip or overwrite the platform headers, so a header-only check returns a false negative for exactly the security-conscious companies you may most want to find. In those setups DNS often still tells the truth—or the reverse: a domain whose DNS routes through a CDN hides the WP Engine CNAME while the platform headers pass through the edge untouched. The practical rule: check both layers, and treat a hit on either as a confirmation. That is what the API does in a single request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual Detection Methods (and Their Limits)
&lt;/h2&gt;

&lt;p&gt;For one domain, the two commands above—&lt;code&gt;dig ... CNAME +short&lt;/code&gt; and &lt;code&gt;curl -sI ... | grep -iE "wpe|x-powered-by"&lt;/code&gt;—are all you need. The limits appear when the task changes shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scale.&lt;/strong&gt; Checking two layers by hand across a 1,000-domain prospect list is a script-writing project with retries, timeouts, and rate limiting to solve before you see a single result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chain resolution.&lt;/strong&gt; &lt;code&gt;dig +short&lt;/code&gt; shows one CNAME hop. Real domains resolve through chains—vanity host to CDN to platform—and the WP Engine hostname may sit two hops deep, where a naive check misses it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context.&lt;/strong&gt; A manual check answers exactly one question. An API scan returns the entire stack—CMS, page builder, analytics, marketing tools—so the same request that confirms WP Engine also scores the lead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Detect WP Engine with the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;The API runs the header and DNS checks together, follows CNAME chains, and returns everything else it finds along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Domain Check with /analyze (curl example)
&lt;/h3&gt;

&lt;p&gt;Try it right now against the public demo endpoint—no API key required. The demo is IP-rate-limited, so use it for spot checks rather than bulk scans:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "WP Engine")'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"WP Engine"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"PaaS"&lt;/span&gt;, &lt;span class="s2"&gt;"Hosting"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"WP Engine is a website hosting provider."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://wpengine.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"wpengine.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;source&lt;/code&gt; field tells you which layer produced the evidence. A &lt;code&gt;source: "http"&lt;/code&gt; entry at confidence 100 came from the platform headers—&lt;code&gt;X-Powered-By: WP Engine&lt;/code&gt;, &lt;code&gt;WPE-Backend&lt;/code&gt;, or one of the cache diagnostics. When only DNS gives it away, the same technology comes back with &lt;code&gt;source: "dns"&lt;/code&gt; at confidence 80 under the Hosting category instead—reliable, but one step removed from a live header match. A header-level hit also implies WordPress, so expect a WordPress entry alongside it.&lt;/p&gt;

&lt;p&gt;For production use, call &lt;code&gt;/analyze&lt;/code&gt; with your API key. The complete response is shaped like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"domain"&lt;/span&gt;: &lt;span class="s2"&gt;"example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"technologies"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"WP Engine"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"PaaS"&lt;/span&gt;, &lt;span class="s2"&gt;"Hosting"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"WP Engine is a website hosting provider."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://wpengine.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"wpengine.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"WordPress"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CMS"&lt;/span&gt;, &lt;span class="s2"&gt;"Blogs"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"WordPress is a free and open-source content management system written in PHP and paired with a MySQL or MariaDB database. Features include a plugin architecture and a template system."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://wordpress.org"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"WordPress.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;"cpe:2.3:a:wordpress:wordpress:*:*:*:*:*:*:*:*"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"PaaS"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WP Engine"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"Hosting"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WP Engine"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"CMS"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WordPress"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"Blogs"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WordPress"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"meta"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"status_code"&lt;/span&gt;: 200, &lt;span class="s2"&gt;"tech_count"&lt;/span&gt;: 2, &lt;span class="s2"&gt;"scan_depth"&lt;/span&gt;: &lt;span class="s2"&gt;"full"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"cached"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
&lt;span class="s2"&gt;"response_ms"&lt;/span&gt;: 1842
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The top-level &lt;code&gt;categories&lt;/code&gt; map groups every detection by category so you can slice the stack without iterating the array. The &lt;code&gt;meta&lt;/code&gt; object carries the HTTP &lt;code&gt;status_code&lt;/code&gt;, the &lt;code&gt;tech_count&lt;/code&gt;, and the &lt;code&gt;scan_depth&lt;/code&gt;; &lt;code&gt;response_ms&lt;/code&gt; and &lt;code&gt;cached&lt;/code&gt; sit at the top level, not inside &lt;code&gt;meta&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;meta.scan_depth&lt;/code&gt; matters for list building. A value of &lt;code&gt;"full"&lt;/code&gt; means the HTTP fetch succeeded and the header check ran. A value of &lt;code&gt;"partial"&lt;/code&gt; means the site blocked or timed out the HTTP request and only the DNS and TLS layers completed. Because WP Engine is also detectable from its CNAME suffixes, a &lt;code&gt;"partial"&lt;/code&gt; scan can still confirm it—but an &lt;em&gt;absent&lt;/em&gt; WP Engine entry on a &lt;code&gt;"partial"&lt;/code&gt; scan is an unknown, not a no. Those domains belong in a retry queue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scanning a Lead List with /analyze/batch
&lt;/h3&gt;

&lt;p&gt;For list building, &lt;code&gt;POST /analyze/batch&lt;/code&gt; accepts up to 10 URLs per request and analyzes them concurrently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["example.com", "example.org", "example.net"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response wraps one result object per URL, each with the same shape as a single &lt;code&gt;/analyze&lt;/code&gt; response, plus batch-level counters:&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;"results"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.net"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"total_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2341&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"successful"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building a WP Engine Prospect List Workflow
&lt;/h2&gt;

&lt;p&gt;Because each batch &lt;code&gt;result&lt;/code&gt; matches the single-domain shape, the filtering logic is identical at any scale. Here is a complete, copy-pasteable pipeline using nothing but &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and &lt;code&gt;jq&lt;/code&gt;. It reads &lt;code&gt;domains.txt&lt;/code&gt; (one domain per line), sends batches of 10, and appends every WP Engine-confirmed domain to &lt;code&gt;wpengine_leads.csv&lt;/code&gt; with the detection source and tech count:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# find-wpengine.sh — filter a domain list down to WP Engine-confirmed leads&lt;/span&gt;
&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"detectzestack.p.rapidapi.com"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain,source,tech_count"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; wpengine_leads.csv

&lt;span class="c"&gt;# Process domains.txt in batches of 10 (the /analyze/batch maximum)&lt;/span&gt;
xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 10 &amp;lt; domains.txt | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; batch&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nv"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="nv"&gt;$batch&lt;/span&gt; | jq &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; | jq &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'{urls: .}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: &lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$urls&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; |
jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result != null)
| .result as $r
| ($r.technologies[] | select(.name == "WP Engine")) as $wpe
| [$r.domain, $wpe.source, ($r.meta.tech_count | tostring)]
| @csv'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; wpengine_leads.csv
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; wpengine_leads.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 1,000-domain list becomes 100 batch calls. Recording &lt;code&gt;$wpe.source&lt;/code&gt; per row lets you split header-confirmed hits from DNS-only ones downstream, and &lt;code&gt;select(.result != null)&lt;/code&gt; skips domains that failed to resolve (those come back with an &lt;code&gt;error&lt;/code&gt; field instead of a &lt;code&gt;result&lt;/code&gt;). Three refinements worth making before outreach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Split by source.&lt;/strong&gt; An &lt;code&gt;http&lt;/code&gt;-sourced hit at confidence 100 means the platform headers are live on the response right now. A &lt;code&gt;dns&lt;/code&gt;-sourced hit at confidence 80 means the domain routes to a WP Engine hostname. Both are real customers; the first is the stronger opener.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-reference the rest of the stack.&lt;/strong&gt; The full &lt;code&gt;technologies&lt;/code&gt; array came back with every row you kept. WP Engine plus Elementor is an agency-built marketing site; WP Engine plus WooCommerce is a store with revenue riding on uptime—different pitches to different buyers. The broader version of this segmentation is covered in &lt;a href="https://detectzestack.com/blog/find-companies-using-wordpress" rel="noopener noreferrer"&gt;finding companies using WordPress&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score by &lt;code&gt;meta.tech_count&lt;/code&gt;.&lt;/strong&gt; Tech count is a rough proxy for stack maturity, useful for prioritizing which confirmed leads get personal outreach first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Feeding these signals into a scoring model is covered in our &lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;lead enrichment pipeline guide&lt;/a&gt;, and the throughput, retry, and rate-limit mechanics are in &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;how to batch scan 1,000 websites&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Widen the net to all managed WordPress hosts. WP Engine’s neighbors—Kinsta (.kinsta.cloud), Pantheon (.pantheonsite.io), Flywheel (.flywheelsites.com), and WordPress VIP (.go-vip.net)—are all detectable from their own CNAME suffixes in the same scan. If your real qualifier is “pays for managed WordPress” rather than “WP Engine specifically,” widen the jq filter to match any of them; every result row already contains the data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Get Started with a Free API Key
&lt;/h2&gt;

&lt;p&gt;The free Basic plan includes 100 requests per month with no credit card—enough to validate the pipeline on a sample of your prospect list before scaling up. Sign-up is instant through RapidAPI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a key at &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;rapidapi.com/mlugoapx/api/detectzestack&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Spot-check a domain you know: &lt;code&gt;curl -s "https://detectzestack.com/demo?url=yourdomain.com" | jq '.technologies[].name'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the batch script above against your first 100 domains.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Finding companies using WP Engine comes down to reading two layers well: the &lt;code&gt;X-Powered-By: WP Engine&lt;/code&gt;, &lt;code&gt;WPE-Backend&lt;/code&gt;, and cache-diagnostic response headers, and the &lt;code&gt;.wpengine.com&lt;/code&gt;, &lt;code&gt;.wpenginepowered.com&lt;/code&gt;, and &lt;code&gt;.wpeproxy.com&lt;/code&gt; DNS CNAMEs. Headers are the strongest signal; DNS is the reliable backup that still works when the HTTP fetch is blocked—and every confirmed hit doubles as a WordPress confirmation with hosting budget attached. A single &lt;code&gt;/analyze&lt;/code&gt; call answers the one-domain question, &lt;code&gt;/analyze/batch&lt;/code&gt; turns a raw list into a WP Engine-confirmed lead list, and the &lt;code&gt;source&lt;/code&gt; and &lt;code&gt;meta.scan_depth&lt;/code&gt; fields tell you how much to trust each row. Swap the &lt;code&gt;jq&lt;/code&gt; filter and the same pipeline segments by Kinsta, Pantheon, or any other detectable technology instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-wordpress" rel="noopener noreferrer"&gt;Find Companies Using WordPress: Build Targeted Lead Lists&lt;/a&gt; — The CMS-level version of this playbook; WP Engine narrows it to paying hosts&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;How to Check if a Website Uses WordPress&lt;/a&gt; — Manual and API methods for single-domain WordPress detection&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-elementor" rel="noopener noreferrer"&gt;Find Companies Using Elementor: Technographic API Guide&lt;/a&gt; — The page-builder filter that stacks cleanly on a WP Engine list&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/dns-based-technology-detection" rel="noopener noreferrer"&gt;DNS-Based Technology Detection&lt;/a&gt; — How CNAME chain resolution surfaces hosting that headers hide&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Deep dive on /analyze/batch throughput, retries, and a Python scanner&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt; — Turning raw detections into scored, routable leads&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Detect cdnjs on Any Website (API Guide)</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Tue, 30 Jun 2026 14:00:53 +0000</pubDate>
      <link>https://dev.to/detectzestack/how-to-detect-cdnjs-on-any-website-api-guide-5h76</link>
      <guid>https://dev.to/detectzestack/how-to-detect-cdnjs-on-any-website-api-guide-5h76</guid>
      <description>&lt;p&gt;cdnjs is one of the most widely used free public CDNs on the web. It is a community-run, open-source library-delivery service hosted on Cloudflare's network, and it lets a developer drop a single &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag into a page to pull in jQuery, Font Awesome, Lodash, or almost any popular open-source package without hosting a file. That convenience is exactly why “loads assets from cdnjs” is a useful detection signal: it tells you something concrete about how a team builds and ships its front end.&lt;/p&gt;

&lt;p&gt;This guide walks through detecting cdnjs on a website—what it actually is, where it shows up in a page's source, how to spot it manually, and how a single DetectZeStack API call returns cdnjs along with the specific libraries and versions it is delivering. We will start with a one-line check you can run right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is cdnjs and Why Detect It
&lt;/h2&gt;

&lt;p&gt;cdnjs (short for “CDN for JavaScript”) is a free, open-source content delivery service that mirrors thousands of popular front-end libraries and serves them from the &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt; hostname. Where an infrastructure CDN like Cloudflare or Amazon CloudFront proxies a whole site's traffic, cdnjs does something narrower: it hands out versioned copies of &lt;em&gt;other people's&lt;/em&gt; open-source code so a page does not have to bundle and self-host them.&lt;/p&gt;

&lt;p&gt;A confirmed cdnjs reference is a small but specific window into a team's front-end habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They lean on public CDNs for dependencies.&lt;/strong&gt; Loading libraries from &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt; rather than bundling and self-hosting them is a deliberate choice. It often signals a leaner build setup—static sites, server-rendered pages, or templates where a script tag is faster than running a bundler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It usually arrives with the library it delivers.&lt;/strong&gt; cdnjs rarely travels alone. The same page that references it is almost always loading a detectable library—jQuery, Font Awesome, a charting or animation library—so one detection often hands you a slice of the front-end stack as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It hints at a supply-chain posture.&lt;/strong&gt; Teams that pull live third-party scripts from a public CDN have a different dependency surface than teams that vendor everything. For security tooling, software-composition-analysis, or subresource-integrity products, that distinction is the qualifier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same detection pipeline applies to any technology DetectZeStack recognizes. We have companion guides for the sibling library-delivery CDN &lt;a href="https://detectzestack.com/blog/find-companies-using-jsdelivr" rel="noopener noreferrer"&gt;jsDelivr&lt;/a&gt; and for &lt;a href="https://detectzestack.com/blog/find-companies-using-google-hosted-libraries" rel="noopener noreferrer"&gt;Google Hosted Libraries&lt;/a&gt;—the fingerprint changes, the workflow stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  How cdnjs Shows Up in a Website's Source
&lt;/h2&gt;

&lt;p&gt;cdnjs is a &lt;em&gt;library-delivery&lt;/em&gt; CDN. It exists to serve versioned, open-source assets—a specific build of jQuery, a pinned release of Font Awesome, a particular Lodash version—straight from Cloudflare-hosted mirrors. A company does not put its own domain behind cdnjs; it references cdnjs from inside its pages to fetch other people's code.&lt;/p&gt;

&lt;p&gt;That has a direct consequence for detection. Finding cdnjs on a site does not tell you who hosts the site or how its traffic is proxied. It tells you the page intentionally pulls at least one third-party asset from cdnjs, and it points you at &lt;em&gt;which&lt;/em&gt; asset when that asset is itself fingerprintable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script tags pointing to cdnjs.cloudflare.com
&lt;/h3&gt;

&lt;p&gt;Every cdnjs reference resolves to the same hostname. In the page source it looks like an ordinary script or stylesheet link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The constant across all of them is the &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt; host. That single string is the primary fingerprint: if it appears in a &lt;code&gt;script src&lt;/code&gt; or a &lt;code&gt;link href&lt;/code&gt; in the served HTML, the page references cdnjs. It is also why cdnjs implies Cloudflare—the service is hosted on Cloudflare's network, so a cdnjs match means the page is pulling code from a Cloudflare-hosted origin, distinct from the whole site being proxied through Cloudflare.&lt;/p&gt;

&lt;h3&gt;
  
  
  Library and version fingerprints cdnjs leaves behind
&lt;/h3&gt;

&lt;p&gt;cdnjs URLs are unusually informative because the path is structured: &lt;code&gt;/ajax/libs/&amp;lt;library&amp;gt;/&amp;lt;version&amp;gt;/&amp;lt;file&amp;gt;&lt;/code&gt;. The example above encodes the library (&lt;code&gt;jquery&lt;/code&gt;) and the exact version (&lt;code&gt;3.6.0&lt;/code&gt;) right in the URL. That structure means two things show up in a single page fetch—the delivery method (cdnjs) and the delivered library, frequently with its version parsed straight from the path.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;What It Tells You&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cdnjs host reference&lt;/td&gt;
&lt;td&gt;cdnjs.cloudflare.com&lt;/td&gt;
&lt;td&gt;cdnjs confirmed (CDN)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivered library + version&lt;/td&gt;
&lt;td&gt;.../ajax/libs/jquery/3.6.0/jquery.min.js&lt;/td&gt;
&lt;td&gt;jQuery confirmed, version parsed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted library&lt;/td&gt;
&lt;td&gt;/static/js/jquery.min.js&lt;/td&gt;
&lt;td&gt;Library detected, no cdnjs signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No cdnjs reference&lt;/td&gt;
&lt;td&gt;(none in HTML)&lt;/td&gt;
&lt;td&gt;Page does not load assets from cdnjs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Manual Ways to Detect cdnjs (and Their Limits)
&lt;/h2&gt;

&lt;p&gt;Because cdnjs lives in the page body, you can spot the raw signal yourself without any tooling. The fastest check is a single &lt;code&gt;curl&lt;/code&gt; piped into &lt;code&gt;grep&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"cdnjs&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;cloudflare&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;com"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
cdnjs.cloudflare.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One match is enough to confirm the page references cdnjs. To see exactly &lt;em&gt;what&lt;/em&gt; it is pulling, widen the pattern to capture the full URLs and read the library and version out of each path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com &lt;span class="se"&gt;\&lt;/span&gt;
| &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s2"&gt;"cdnjs&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;cloudflare&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;com/ajax/libs/[^&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;']+"&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but it has real limits when you move past one site. The reference only appears if it is present in the server-rendered HTML—a script injected later by client-side JavaScript, or one loaded through a tag manager, may not show up in a plain &lt;code&gt;curl&lt;/code&gt;. You also have to parse each path yourself to turn it into structured data, and running this across hundreds of domains means writing your own concurrency, retry, and timeout handling. That is the gap a detection API closes: it normalizes the same body signal into clean JSON and runs it at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detect cdnjs Programmatically with the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;When DetectZeStack fetches a page, it scans the HTML for script and link references to &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt;. A match returns cdnjs under the &lt;strong&gt;CDN&lt;/strong&gt; category at confidence 100, with &lt;code&gt;source: "http"&lt;/code&gt;—because the evidence came directly from the HTTP response body.&lt;/p&gt;

&lt;p&gt;You can try it right now against the public demo endpoint—no API key required. The demo is IP-rate-limited, so use it for spot checks rather than bulk scans:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "cdnjs")'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs is a free distributed JS library delivery service."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://cdnjs.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;cdnjs is matched directly off the &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt; reference in the page and categorized under &lt;code&gt;CDN&lt;/code&gt;. It carries &lt;code&gt;source: "http"&lt;/code&gt; because the evidence came from the HTTP response body, and the &lt;code&gt;version&lt;/code&gt; field is empty—cdnjs itself is a delivery network, not a versioned library, so there is nothing to read a version from. The libraries it delivers are where versions show up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading the technologies, version, and categories fields
&lt;/h3&gt;

&lt;p&gt;When you want the full stack for a domain rather than a filtered slice, call &lt;code&gt;/analyze&lt;/code&gt; with your API key. A page that loads jQuery from cdnjs comes back like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"domain"&lt;/span&gt;: &lt;span class="s2"&gt;"example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"technologies"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs is a free distributed JS library delivery service."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://cdnjs.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"cdnjs.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"jQuery"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"JavaScript libraries"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"jQuery is a JavaScript library designed to simplify HTML DOM tree traversal and manipulation, as well as event handling, CSS animation, and Ajax."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://jquery.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"jQuery.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;"3.6.0"&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Cloudflare"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"Cloudflare is a web-infrastructure and website-security company that provides content-delivery-network services, DDoS mitigation, and ICANN-accredited domain registration services."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://www.cloudflare.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"CloudFlare.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"CDN"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"cdnjs"&lt;/span&gt;, &lt;span class="s2"&gt;"Cloudflare"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"JavaScript libraries"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"jQuery"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"meta"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"status_code"&lt;/span&gt;: 200, &lt;span class="s2"&gt;"tech_count"&lt;/span&gt;: 3, &lt;span class="s2"&gt;"scan_depth"&lt;/span&gt;: &lt;span class="s2"&gt;"full"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"cached"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
&lt;span class="s2"&gt;"response_ms"&lt;/span&gt;: 1842
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three entries from one page. cdnjs is the delivery method; jQuery is the thing being delivered, with its version parsed from the script URL; and Cloudflare appears because cdnjs is hosted on Cloudflare's network and its fingerprint implies Cloudflare. The top-level &lt;code&gt;categories&lt;/code&gt; map groups every detection, so you can pull all CDNs with &lt;code&gt;.categories["CDN"]&lt;/code&gt; without iterating the array. The &lt;code&gt;meta&lt;/code&gt; object carries the HTTP &lt;code&gt;status_code&lt;/code&gt;, the &lt;code&gt;tech_count&lt;/code&gt;, and the &lt;code&gt;scan_depth&lt;/code&gt;; &lt;code&gt;response_ms&lt;/code&gt; and &lt;code&gt;cached&lt;/code&gt; sit at the top level.&lt;/p&gt;

&lt;p&gt;One field to watch for list building is &lt;code&gt;meta.scan_depth&lt;/code&gt;. A value of &lt;code&gt;"full"&lt;/code&gt; means the HTTP fetch succeeded and body detection ran. A value of &lt;code&gt;"partial"&lt;/code&gt; means the site blocked or timed out the HTTP request and only DNS and TLS layers completed—and since cdnjs lives in the body, an absent cdnjs entry on a &lt;code&gt;"partial"&lt;/code&gt; scan tells you nothing. Those domains belong in a retry queue, not your rejects file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The honest limitation: cdnjs detection depends on the HTML actually containing the reference. If a script is injected later by client-side JavaScript that never runs during a server-side fetch, or if the reference sits behind a tag manager, it may not appear in the fetched body. As with any body-fingerprint signal, absence of a detection is an unknown, not proof the site never touches cdnjs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Detecting cdnjs Across Many Sites at Scale
&lt;/h2&gt;

&lt;p&gt;For list building, &lt;code&gt;POST /analyze/batch&lt;/code&gt; accepts up to 10 URLs per request and analyzes them concurrently. Each entry in the response carries either a full analysis result or an error for domains that could not be fetched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["example.com", "getbootstrap.com", "wordpress.org"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response wraps one result object per URL, each with the same shape as a single &lt;code&gt;/analyze&lt;/code&gt; response:&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;"results"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getbootstrap.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wordpress.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"total_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2341&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"successful"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="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;Because each &lt;code&gt;result&lt;/code&gt; matches the single-domain shape, the filtering logic is identical whether you scan one domain or a thousand. Here is a complete, copy-pasteable pipeline using nothing but &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and &lt;code&gt;jq&lt;/code&gt;. It reads &lt;code&gt;domains.txt&lt;/code&gt; (one domain per line), sends batches of 10 to &lt;code&gt;/analyze/batch&lt;/code&gt;, and appends every domain where cdnjs is detected to &lt;code&gt;cdnjs_leads.csv&lt;/code&gt;, recording the tech count alongside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# find-cdnjs.sh — filter a domain list down to cdnjs-confirmed sites&lt;/span&gt;
&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"detectzestack.p.rapidapi.com"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain,tech_count"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; cdnjs_leads.csv

&lt;span class="c"&gt;# Process domains.txt in batches of 10 (the /analyze/batch maximum)&lt;/span&gt;
xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 10 &amp;lt; domains.txt | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; batch&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nv"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="nv"&gt;$batch&lt;/span&gt; | jq &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; | jq &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'{urls: .}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: &lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$urls&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; |
jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result != null)
| .result as $r
| select([$r.technologies[].name] | index("cdnjs"))
| [$r.domain, ($r.meta.tech_count | tostring)]
| @csv'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; cdnjs_leads.csv
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; cdnjs_leads.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 1,000-domain list becomes 100 batch calls. The &lt;code&gt;index("cdnjs")&lt;/code&gt; guard keeps a domain whenever cdnjs appears in its technology list, and &lt;code&gt;select(.result != null)&lt;/code&gt; skips domains that failed to resolve (those come back with an &lt;code&gt;error&lt;/code&gt; field instead of a &lt;code&gt;result&lt;/code&gt;). For a deeper treatment of batch throughput, retries, and a production Python scanner, see &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;how to batch scan 1,000 websites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to segment by the library cdnjs is delivering rather than just the delivery method, widen the filter to capture the co-detected technologies—the same &lt;code&gt;technologies&lt;/code&gt; array already carries jQuery, Font Awesome, and whatever else the page pulls in. Our guides on &lt;a href="https://detectzestack.com/blog/how-to-detect-jquery" rel="noopener noreferrer"&gt;detecting jQuery&lt;/a&gt; and the broader &lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;JavaScript framework detection&lt;/a&gt; cover those fingerprints in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  cdnjs vs Other JavaScript CDNs
&lt;/h2&gt;

&lt;p&gt;“CDN” is an overloaded word, and it helps to be precise about where cdnjs sits. There are two very different things both called CDNs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th&gt;Detected From&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure CDN&lt;/td&gt;
&lt;td&gt;Cloudflare, Fastly, Amazon CloudFront, Akamai&lt;/td&gt;
&lt;td&gt;DNS CNAME, response headers, TLS certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library-delivery CDN&lt;/td&gt;
&lt;td&gt;cdnjs, jsDelivr, unpkg, Google Hosted Libraries&lt;/td&gt;
&lt;td&gt;Script &amp;amp; link references in the page HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An infrastructure CDN proxies the whole site, so it shows up in the site's DNS, headers, and certificate—the layer covered in &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;how to detect a website's CDN and hosting provider&lt;/a&gt; and, for one specific provider, &lt;a href="https://detectzestack.com/blog/find-companies-using-amazon-cloudfront" rel="noopener noreferrer"&gt;finding companies using Amazon CloudFront&lt;/a&gt;. cdnjs sits in the other column: it is detected purely from references inside the served HTML, alongside its peers jsDelivr (&lt;code&gt;cdn.jsdelivr.net&lt;/code&gt;), unpkg (&lt;code&gt;unpkg.com&lt;/code&gt;), and Google Hosted Libraries (&lt;code&gt;ajax.googleapis.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;cdnjs is closest to jsDelivr—both serve open-source libraries from a public mirror—with one wrinkle: cdnjs is hosted on Cloudflare, so its detection implies Cloudflare, while jsDelivr is independent. The flip side of both is the self-hosted case. A team that runs a bundler and ships its libraries from its own domain will load, say, jQuery from &lt;code&gt;/static/js/jquery.min.js&lt;/code&gt;—no cdnjs reference at all. The library is still detectable on its own fingerprint, but the delivery signal is absent. A missing cdnjs detection does not mean the site avoids jQuery; it means the site does not &lt;em&gt;fetch jQuery from cdnjs&lt;/em&gt;. Keep that distinction in mind when you read negatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Your API Key and Start Detecting cdnjs
&lt;/h2&gt;

&lt;p&gt;The free tier includes 100 requests per month with no credit card—enough to validate the pipeline on a sample of your domain list before scaling up. Sign-up is instant through RapidAPI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a key at &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;rapidapi.com/mlugoapx/api/detectzestack&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Spot-check a domain you know: &lt;code&gt;curl -s "https://detectzestack.com/demo?url=yourdomain.com" | jq '.technologies[].name'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the batch script above against your first 100 domains.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Detecting cdnjs comes down to reading one thing well: a &lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt; reference in the page HTML. Because cdnjs is a library-delivery CDN rather than an infrastructure one, it is detected from the body, not from DNS or headers—and the real prize is usually the library it carries, whose name and version are encoded right in the URL path and returned alongside it. A single &lt;code&gt;/analyze&lt;/code&gt; call answers the one-domain question; &lt;code&gt;/analyze/batch&lt;/code&gt; turns a raw domain list into a cdnjs-confirmed list; and &lt;code&gt;meta.scan_depth&lt;/code&gt; tells you which negatives are real and which are unknowns worth a retry. Swap the &lt;code&gt;jq&lt;/code&gt; filter and the same pipeline segments by front-end library, infrastructure CDN, or backend runtime instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-jsdelivr" rel="noopener noreferrer"&gt;Find Companies Using jsDelivr&lt;/a&gt; — The sibling library-delivery CDN (cdn.jsdelivr.net), detected from the page HTML the same way&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-google-hosted-libraries" rel="noopener noreferrer"&gt;Find Companies Using Google Hosted Libraries&lt;/a&gt; — The other major library-delivery CDN (ajax.googleapis.com), with the delivered library and version encoded in the URL path&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;How to Detect the CDN and Hosting Provider of Any Website&lt;/a&gt; — The infrastructure-CDN layer that sits in front of a site, detected via DNS, headers, and TLS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-jquery" rel="noopener noreferrer"&gt;How to Detect jQuery on a Website&lt;/a&gt; — One of the most common libraries delivered over cdnjs, and its own fingerprints&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-amazon-cloudfront" rel="noopener noreferrer"&gt;Find Companies Using Amazon CloudFront&lt;/a&gt; — An infrastructure CDN detected from headers, DNS, and TLS instead of the page body&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Deep dive on /analyze/batch throughput, retries, and a Python scanner&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt; — Turning raw detections into scored, routable leads&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Find Companies Using jsDelivr: Technographic API Guide</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Mon, 22 Jun 2026 14:00:54 +0000</pubDate>
      <link>https://dev.to/detectzestack/find-companies-using-jsdelivr-technographic-api-guide-48aa</link>
      <guid>https://dev.to/detectzestack/find-companies-using-jsdelivr-technographic-api-guide-48aa</guid>
      <description>&lt;p&gt;jsDelivr is one of the most widely used free public CDNs on the web. It serves open-source files directly from the npm registry and GitHub repositories, which means a developer can drop a single &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag into a page and pull in Bootstrap, Chart.js, a jQuery plugin, or almost any published package without hosting a thing themselves. That convenience is exactly what makes “uses jsDelivr” an interesting technographic signal: it tells you something about how a team builds and ships front-end code.&lt;/p&gt;

&lt;p&gt;This guide explains what jsDelivr usage actually reveals about a company, why it is detected differently from an infrastructure CDN like Cloudflare, and how to turn a raw domain list into a jsDelivr-confirmed lead list with the DetectZeStack API—starting with a single curl command you can run right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Find Companies Using jsDelivr?
&lt;/h2&gt;

&lt;p&gt;Technographic data—what technology a company runs—is frequently a stronger qualifier than firmographics alone. A confirmed jsDelivr reference is a small but specific window into a team's front-end habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They lean on public CDNs for dependencies.&lt;/strong&gt; Loading libraries from &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; rather than bundling and self-hosting them is a deliberate choice. It often signals a leaner build setup—static sites, server-rendered pages, or templates where pulling a script tag is faster than running a bundler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It usually comes bundled with the library it delivers.&lt;/strong&gt; jsDelivr rarely travels alone. The same page that references it is almost always loading a detectable library—Bootstrap, Chart.js, a charting or carousel plugin—so one detection often hands you the front-end stack as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It hints at a security and supply-chain posture.&lt;/strong&gt; Teams that pull live third-party scripts from a public CDN have a different dependency surface than teams that vendor everything. For security tooling, SCA, or subresource-integrity products, that distinction is the qualifier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same pipeline applies to any detectable technology. We have companion guides for &lt;a href="https://detectzestack.com/blog/find-companies-using-node-js" rel="noopener noreferrer"&gt;finding companies using Node.js&lt;/a&gt; and the broader topic of &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;detecting a site's CDN and hosting provider&lt;/a&gt;—the filter changes, the workflow stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  What jsDelivr Tells You About a Tech Stack
&lt;/h2&gt;

&lt;p&gt;jsDelivr is a &lt;em&gt;library-delivery&lt;/em&gt; CDN. It exists to serve versioned, open-source assets—a specific build of Bootstrap, a pinned release of Chart.js, a Vue component—straight from npm or GitHub. A company does not put its own domain behind jsDelivr; it references jsDelivr from inside its pages to fetch other people's code.&lt;/p&gt;

&lt;p&gt;That has a direct consequence for what a detection means. Finding jsDelivr on a site does not tell you who hosts the site or how its traffic is proxied. It tells you the page intentionally pulls at least one third-party asset from a public CDN, and it points you at &lt;em&gt;which&lt;/em&gt; asset when that asset is itself fingerprintable.&lt;/p&gt;

&lt;h3&gt;
  
  
  jsDelivr vs Self-Hosted Libraries and Other CDNs
&lt;/h3&gt;

&lt;p&gt;It is worth being precise about where jsDelivr sits, because “CDN” is an overloaded word. There are two very different things both called CDNs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th&gt;Detected From&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure CDN&lt;/td&gt;
&lt;td&gt;Cloudflare, Fastly, CloudFront, Akamai&lt;/td&gt;
&lt;td&gt;DNS CNAME, response headers, TLS certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library-delivery CDN&lt;/td&gt;
&lt;td&gt;jsDelivr, cdnjs, unpkg, Google Hosted Libraries&lt;/td&gt;
&lt;td&gt;Script &amp;amp; link references in the page HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An infrastructure CDN proxies the whole site, so it shows up in the site's DNS, headers, and certificate—the layer covered in &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;how to detect a website's CDN and hosting provider&lt;/a&gt;. jsDelivr leaves none of those marks, because it never touches the site's own domain. It appears only as a reference inside the served HTML, alongside its peers cdnjs (&lt;code&gt;cdnjs.cloudflare.com&lt;/code&gt;), unpkg (&lt;code&gt;unpkg.com&lt;/code&gt;), and Google Hosted Libraries (&lt;code&gt;ajax.googleapis.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The flip side is the self-hosted case. A team that runs a bundler and ships its libraries from its own domain will load, say, Bootstrap from &lt;code&gt;/static/js/bootstrap.min.js&lt;/code&gt;—no jsDelivr reference at all. The library is still detectable on its own fingerprint, but the delivery signal is absent. In other words: a missing jsDelivr detection does not mean the site avoids Bootstrap; it means the site does not &lt;em&gt;fetch Bootstrap from jsDelivr&lt;/em&gt;. Keep that distinction in mind when you read negatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  How DetectZeStack Detects jsDelivr
&lt;/h2&gt;

&lt;p&gt;Because jsDelivr lives in the page body, detection is a body-fingerprint match, not a DNS or header lookup. When DetectZeStack fetches a page, it scans the HTML for script and link references to &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt;. A match returns jsDelivr under the &lt;strong&gt;CDN&lt;/strong&gt; category, at confidence 100, with &lt;code&gt;source: "http"&lt;/code&gt;—because the evidence came directly from the HTTP response body.&lt;/p&gt;

&lt;p&gt;You can spot the same raw signal yourself with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"cdn&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;jsdelivr&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;net"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
cdn.jsdelivr.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One match is enough to confirm the page references jsDelivr. The value the API adds is what comes &lt;em&gt;with&lt;/em&gt; it: many of the libraries delivered over jsDelivr have their own fingerprints, so a single scan typically returns jsDelivr plus whatever it is delivering. A page that loads Chart.js from a &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; path, for example, comes back with both jsDelivr (under CDN) and Chart.js as separate entries—often with a version parsed straight from the URL.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;What It Tells You&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jsDelivr script source&lt;/td&gt;
&lt;td&gt;cdn.jsdelivr.net&lt;/td&gt;
&lt;td&gt;jsDelivr confirmed (CDN)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivered library&lt;/td&gt;
&lt;td&gt;.../npm/chart.js@4/dist/chart.js&lt;/td&gt;
&lt;td&gt;Chart.js confirmed, version parsed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted library&lt;/td&gt;
&lt;td&gt;/static/js/bootstrap.min.js&lt;/td&gt;
&lt;td&gt;Library detected, no jsDelivr signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No jsDelivr reference&lt;/td&gt;
&lt;td&gt;(none in HTML)&lt;/td&gt;
&lt;td&gt;Site does not load assets from jsDelivr&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The honest limitation: jsDelivr detection depends on the HTML actually containing the reference. If a script is injected later by client-side JavaScript that never runs during a server-side fetch, or if the reference sits behind a tag manager, it may not appear in the fetched body. As with any body-fingerprint signal, absence of a detection is an unknown, not proof the site never touches jsDelivr.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  API Example: Detecting jsDelivr With a Single Call
&lt;/h2&gt;

&lt;p&gt;You can try detection right now against the public demo endpoint—no API key required. The demo is IP-rate-limited, so use it for spot checks rather than bulk scans:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "jsDelivr")'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"jsDelivr"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"JSDelivr is a free public CDN for open-source projects. It can serve web files directly from the npm registry and GitHub repositories without any configuration."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://www.jsdelivr.com/"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"jsdelivr-icon.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;jsDelivr is matched directly off the &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; reference in the page and categorized under &lt;code&gt;CDN&lt;/code&gt;. It carries &lt;code&gt;source: "http"&lt;/code&gt; because the evidence came from the HTTP response body, and the &lt;code&gt;version&lt;/code&gt; field is empty—jsDelivr itself is a delivery network, not a versioned library, so there is nothing to read a version from. The libraries it delivers are where versions show up.&lt;/p&gt;

&lt;p&gt;When you want the full stack for a domain rather than a filtered slice, call &lt;code&gt;/analyze&lt;/code&gt; with your API key. The complete response is shaped like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"domain"&lt;/span&gt;: &lt;span class="s2"&gt;"example.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"technologies"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"jsDelivr"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"JSDelivr is a free public CDN for open-source projects. It can serve web files directly from the npm registry and GitHub repositories without any configuration."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://www.jsdelivr.com/"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"jsdelivr-icon.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Chart.js"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"JavaScript graphics"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"Chart.js is a free, open-source JavaScript library for data visualization."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://www.chartjs.org"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"Chart.js.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;"4.4.1"&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"CDN"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"jsDelivr"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"JavaScript graphics"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Chart.js"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"meta"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"status_code"&lt;/span&gt;: 200, &lt;span class="s2"&gt;"tech_count"&lt;/span&gt;: 2, &lt;span class="s2"&gt;"scan_depth"&lt;/span&gt;: &lt;span class="s2"&gt;"full"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="s2"&gt;"cached"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
&lt;span class="s2"&gt;"response_ms"&lt;/span&gt;: 1842
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two entries from one page: jsDelivr as the delivery method and Chart.js as the thing being delivered, with its version parsed from the script URL. The top-level &lt;code&gt;categories&lt;/code&gt; map groups every detection so you can pull all CDNs with &lt;code&gt;.categories["CDN"]&lt;/code&gt; without iterating the array. The &lt;code&gt;meta&lt;/code&gt; object carries the HTTP &lt;code&gt;status_code&lt;/code&gt;, the &lt;code&gt;tech_count&lt;/code&gt;, and the &lt;code&gt;scan_depth&lt;/code&gt;; &lt;code&gt;response_ms&lt;/code&gt; and &lt;code&gt;cached&lt;/code&gt; sit at the top level.&lt;/p&gt;

&lt;p&gt;One field to watch for list building is &lt;code&gt;meta.scan_depth&lt;/code&gt;. A value of &lt;code&gt;"full"&lt;/code&gt; means the HTTP fetch succeeded and body detection ran. A value of &lt;code&gt;"partial"&lt;/code&gt; means the site blocked or timed out the HTTP request and only DNS and TLS layers completed—and since jsDelivr lives in the body, an absent jsDelivr entry on a &lt;code&gt;"partial"&lt;/code&gt; scan tells you nothing. Those domains belong in a retry queue, not your rejects file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a List of Companies Using jsDelivr at Scale
&lt;/h3&gt;

&lt;p&gt;For list building, &lt;code&gt;POST /analyze/batch&lt;/code&gt; accepts up to 10 URLs per request and analyzes them concurrently. Each entry in the response carries either a full analysis result or an error for domains that could not be fetched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["example.com", "getbootstrap.com", "wordpress.org"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response wraps one result object per URL, each with the same shape as a single &lt;code&gt;/analyze&lt;/code&gt; response:&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;"results"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getbootstrap.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wordpress.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"...full analysis..."&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;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"total_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2341&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"successful"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="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;Because each &lt;code&gt;result&lt;/code&gt; matches the single-domain shape, the filtering logic is identical whether you scan one domain or a thousand. Here is a complete, copy-pasteable pipeline using nothing but &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and &lt;code&gt;jq&lt;/code&gt;. It reads &lt;code&gt;domains.txt&lt;/code&gt; (one domain per line), sends batches of 10 to &lt;code&gt;/analyze/batch&lt;/code&gt;, and appends every domain where jsDelivr is detected to &lt;code&gt;jsdelivr_leads.csv&lt;/code&gt;, recording the tech count alongside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# find-jsdelivr.sh — filter a domain list down to jsDelivr-confirmed leads&lt;/span&gt;
&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"detectzestack.p.rapidapi.com"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain,tech_count"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; jsdelivr_leads.csv

&lt;span class="c"&gt;# Process domains.txt in batches of 10 (the /analyze/batch maximum)&lt;/span&gt;
xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 10 &amp;lt; domains.txt | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; batch&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nv"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="nv"&gt;$batch&lt;/span&gt; | jq &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; | jq &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'{urls: .}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: &lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$urls&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; |
jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result != null)
| .result as $r
| select([$r.technologies[].name] | index("jsDelivr"))
| [$r.domain, ($r.meta.tech_count | tostring)]
| @csv'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; jsdelivr_leads.csv
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; jsdelivr_leads.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 1,000-domain list becomes 100 batch calls. The &lt;code&gt;index("jsDelivr")&lt;/code&gt; guard keeps a domain whenever jsDelivr appears in its technology list, and &lt;code&gt;select(.result != null)&lt;/code&gt; skips domains that failed to resolve (those come back with an &lt;code&gt;error&lt;/code&gt; field instead of a &lt;code&gt;result&lt;/code&gt;). For a deeper treatment of batch throughput, retries, and a production Python scanner, see &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;how to batch scan 1,000 websites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to segment by the library jsDelivr is delivering rather than just the delivery method, widen the filter to capture the co-detected technologies—the same &lt;code&gt;technologies&lt;/code&gt; array already carries Chart.js, Bootstrap, jQuery, and whatever else the page pulls in. Our guides on &lt;a href="https://detectzestack.com/blog/how-to-detect-jquery" rel="noopener noreferrer"&gt;detecting jQuery&lt;/a&gt; and the broader &lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;JavaScript framework detection&lt;/a&gt; cover those fingerprints in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases: Sales, Competitive Intelligence, and Security
&lt;/h2&gt;

&lt;p&gt;A jsDelivr-confirmed list is rarely the end goal on its own—it is the entry point to a more specific segment. Three common ways teams use it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sales and prospecting.&lt;/strong&gt; Pair the jsDelivr flag with the library it delivers. A list of sites pulling a specific charting or UI library from jsDelivr is a precise audience if you sell a competing or complementary front-end product. The delivery method narrows the list; the delivered library qualifies it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive intelligence.&lt;/strong&gt; Scanning a market segment for public-CDN usage tells you how teams in that space build. A cohort that leans heavily on jsDelivr and cdnjs is shipping differently than one that bundles and self-hosts everything—useful context when you are studying how an entire market makes front-end decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and supply-chain mapping.&lt;/strong&gt; Every live third-party script is part of a site's dependency surface. Security teams use technographic scans to inventory which external CDNs a domain pulls executable code from, which feeds subresource-integrity audits and third-party-risk reviews. The CDN category is exactly the layer they need to enumerate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two practical enrichment moves once the list is built: cross-reference the infrastructure CDN to separate “loads libraries from jsDelivr” from “proxied through Cloudflare”—they are independent signals and a site commonly has both—and score by &lt;code&gt;meta.tech_count&lt;/code&gt;, a rough proxy for how built-out a company's front end is. Feeding those signals into a scoring model is covered in our &lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;lead enrichment pipeline guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started With the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;The free tier includes 100 requests per month with no credit card—enough to validate the pipeline on a sample of your prospect list before scaling up. Sign-up is instant through RapidAPI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a key at &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;rapidapi.com/mlugoapx/api/detectzestack&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Spot-check a domain you know: &lt;code&gt;curl -s "https://detectzestack.com/demo?url=yourdomain.com" | jq '.technologies[].name'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the batch script above against your first 100 domains.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Finding companies using jsDelivr comes down to reading one thing well: a &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; reference in the page HTML. Because jsDelivr is a library-delivery CDN rather than an infrastructure one, it is detected from the body, not from DNS or headers—and the real prize is usually the library it carries, which a single scan returns alongside it. A single &lt;code&gt;/analyze&lt;/code&gt; call answers the one-domain question; &lt;code&gt;/analyze/batch&lt;/code&gt; turns a raw domain list into a jsDelivr-confirmed lead list; and &lt;code&gt;meta.scan_depth&lt;/code&gt; tells you which negatives are real and which are unknowns worth a retry. Swap the &lt;code&gt;jq&lt;/code&gt; filter and the same pipeline segments by infrastructure CDN, front-end library, or backend runtime instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;How to Detect the CDN and Hosting Provider of Any Website&lt;/a&gt; — The infrastructure-CDN layer that sits in front of a site, detected via DNS, headers, and TLS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-node-js" rel="noopener noreferrer"&gt;Find Companies Using Node.js&lt;/a&gt; — The same batch workflow filtered for a backend runtime&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-jquery" rel="noopener noreferrer"&gt;How to Detect jQuery on a Website&lt;/a&gt; — One of the most common libraries delivered over jsDelivr, and its own fingerprints&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;How to Detect the JavaScript Framework of a Website&lt;/a&gt; — Segmenting by the front-end library jsDelivr is delivering&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Deep dive on /analyze/batch throughput, retries, and a Python scanner&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt; — Turning raw detections into scored, routable leads&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Find Companies Using MySQL: API Guide for 2026</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Sun, 14 Jun 2026 14:01:17 +0000</pubDate>
      <link>https://dev.to/detectzestack/how-to-find-companies-using-mysql-api-guide-for-2026-59p7</link>
      <guid>https://dev.to/detectzestack/how-to-find-companies-using-mysql-api-guide-for-2026-59p7</guid>
      <description>&lt;p&gt;MySQL has been the default database of the web for two decades. It sits underneath WordPress, Magento, PrestaShop, and a long tail of forums, wikis, and self-hosted tools—which means a list of companies using MySQL is really a list of companies running real, database-backed applications. If you sell database tooling, managed hosting, backup services, migration consulting, or performance monitoring, that list is your pipeline.&lt;/p&gt;

&lt;p&gt;There is a catch, and most guides skip it: &lt;strong&gt;you cannot detect MySQL directly from outside a website.&lt;/strong&gt; The database never talks to the browser. This guide explains how MySQL detection actually works (inference through the application layer), how reliable those inferences are, and how to turn a raw domain list into a MySQL-confirmed prospect list with the DetectZeStack API—single checks, batch scans, and side-by-side comparison included.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build a List of Companies Using MySQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Who Uses MySQL Lists: Sales, DevRel, Security, and Migration Vendors
&lt;/h3&gt;

&lt;p&gt;MySQL technographics serve a wider set of buyers than most technology filters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database and infrastructure vendors.&lt;/strong&gt; Managed MySQL hosting, backup-as-a-service, replication tooling, query performance monitors—every one of these products has “runs MySQL” as its first qualifying question. A confirmed detection replaces a discovery call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration and consulting shops.&lt;/strong&gt; Teams selling PostgreSQL migrations, cloud database moves, or version-upgrade services need to find MySQL estates before they can pitch replacing or modernizing them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevRel and developer marketing.&lt;/strong&gt; If your product integrates with MySQL—an ORM, a CDC pipeline, a caching layer—the companies already running it are the audience for your content and outreach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security teams.&lt;/strong&gt; MySQL detections come with a CPE identifier (&lt;code&gt;cpe:2.3:a:mysql:mysql&lt;/code&gt;), which plugs directly into vulnerability workflows. An external scan of your vendors’ domains tells you which ones run MySQL-backed platforms worth asking about in a security review. Our &lt;a href="https://detectzestack.com/blog/cpe-identifiers-explained-for-security-teams" rel="noopener noreferrer"&gt;CPE guide for security teams&lt;/a&gt; covers that pipeline end to end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow below is the same one we documented for &lt;a href="https://detectzestack.com/blog/find-companies-using-nginx" rel="noopener noreferrer"&gt;finding companies using Nginx&lt;/a&gt; and &lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;finding companies using Stripe&lt;/a&gt;—only the filter changes. What makes the MySQL version interesting is &lt;em&gt;how&lt;/em&gt; the detection happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  How MySQL Detection Works (and Its Limits)
&lt;/h2&gt;

&lt;p&gt;A web server announces itself in the &lt;code&gt;Server&lt;/code&gt; header. A JavaScript framework leaves fingerprints all over the HTML. MySQL does neither—it listens on port 3306 behind a firewall and speaks only to the application. There is no header, cookie, or script tag that says “MySQL.”&lt;/p&gt;

&lt;p&gt;So external detection works by &lt;strong&gt;implication&lt;/strong&gt;. The fingerprint database knows that certain applications are built on MySQL. When one of those applications is detected through its own (very visible) fingerprints, MySQL is added to the result as an implied technology. Detect WordPress, and you have detected MySQL, because WordPress does not run without it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indirect Signals: CMS and Ecommerce Platform Implications
&lt;/h3&gt;

&lt;p&gt;Dozens of detectable platforms carry a MySQL implication. The ones you will encounter most in real scans:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;What It Means for Your List&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WordPress&lt;/td&gt;
&lt;td&gt;CMS / Blogs&lt;/td&gt;
&lt;td&gt;The single biggest MySQL signal on the web—every WordPress site is a MySQL (or MariaDB) site&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Magento&lt;/td&gt;
&lt;td&gt;Ecommerce&lt;/td&gt;
&lt;td&gt;Larger ecommerce operations with real database load—prime targets for performance tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrestaShop&lt;/td&gt;
&lt;td&gt;Ecommerce&lt;/td&gt;
&lt;td&gt;SMB ecommerce, heavily represented in Europe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenCart&lt;/td&gt;
&lt;td&gt;Ecommerce&lt;/td&gt;
&lt;td&gt;Self-hosted SMB stores, often on shared or VPS hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shopware&lt;/td&gt;
&lt;td&gt;Ecommerce&lt;/td&gt;
&lt;td&gt;Mid-market ecommerce, strong in the DACH region&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flarum / Invision Power Board&lt;/td&gt;
&lt;td&gt;Forums&lt;/td&gt;
&lt;td&gt;Community-run infrastructure with long-lived databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookStack / MantisBT / Piwigo&lt;/td&gt;
&lt;td&gt;Self-hosted tools&lt;/td&gt;
&lt;td&gt;Teams that self-host internal tooling—a strong “runs own infrastructure” signal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two honest caveats before you build a pipeline on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MySQL vs MariaDB is invisible from outside.&lt;/strong&gt; WordPress and most of the platforms above run equally well on MariaDB, a drop-in replacement. External detection cannot tell which fork is actually installed—treat the detection as “MySQL-compatible database” when precision matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not every MySQL-implying platform is in the chain.&lt;/strong&gt; Notably, Drupal supports several databases and therefore does &lt;em&gt;not&lt;/em&gt; imply MySQL in the fingerprint data, even though many Drupal sites do run it. The implication list is deliberately conservative: it only includes platforms where MySQL is a hard requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Server-Side Databases Are Harder to Detect Than Frontend Tech
&lt;/h3&gt;

&lt;p&gt;This inference model has an asymmetry you need to internalize before trusting your lead list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positives are strong.&lt;/strong&gt; If the API reports MySQL, a MySQL-requiring platform was detected at full confidence. The implication is definitional, not statistical—there is no such thing as a WordPress site without a MySQL-compatible database behind it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negatives are unknowns.&lt;/strong&gt; A custom Laravel app, a Rails monolith, or a Django site can all run MySQL without exposing any platform fingerprint that implies it. No detection does &lt;em&gt;not&lt;/em&gt; mean no MySQL—it means no visible evidence. Score these domains as “unknown,” not “disqualified.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the database equivalent of the CDN-masking problem we covered in the &lt;a href="https://detectzestack.com/blog/find-companies-using-nginx" rel="noopener noreferrer"&gt;Nginx guide&lt;/a&gt;: external scanning gives you high-precision positives and ambiguous negatives. Good pipelines keep the two piles separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find MySQL-Backed Sites with the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;The API runs the full detection pass—HTTP fingerprints, DNS records, and TLS certificates—in one call, resolves the implication chains, and returns structured JSON. You can try it right now against the public demo endpoint, no API key required (it is IP-rate-limited, so use it for spot checks, not bulk scans):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=wordpress.org"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "MySQL")'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"MySQL"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Databases"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"MySQL is an open-source relational database management system."&lt;/span&gt;,
&lt;span class="s2"&gt;"website"&lt;/span&gt;: &lt;span class="s2"&gt;"https://mysql.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"icon"&lt;/span&gt;: &lt;span class="s2"&gt;"MySQL.svg"&lt;/span&gt;,
&lt;span class="s2"&gt;"cpe"&lt;/span&gt;: &lt;span class="s2"&gt;"cpe:2.3:a:mysql:mysql:*:*:*:*:*:*:*:*"&lt;/span&gt;,
&lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"http"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a real response. MySQL appears under the &lt;code&gt;Databases&lt;/code&gt; category at confidence 100—the implying platform (WordPress, in this case) was an HTTP-layer match, and the implication inherits its confidence. The &lt;code&gt;cpe&lt;/code&gt; field is ready for vulnerability tooling. Note there is no &lt;code&gt;version&lt;/code&gt; field: an implied database carries no version information, because the version lives server-side where no scanner can see it.&lt;/p&gt;

&lt;p&gt;The top-level &lt;code&gt;categories&lt;/code&gt; map gives you a shortcut—you can check for any database without iterating the technologies array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=wordpress.org"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.categories["Databases"]'&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="s2"&gt;"MySQL"&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Single Domain Check with /analyze
&lt;/h3&gt;

&lt;p&gt;With an API key, &lt;code&gt;/analyze&lt;/code&gt; is the authenticated equivalent—same response shape, your own rate limits, and results cached for repeat lookups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=example-store.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'{domain, mysql: (.categories["Databases"] // [] | contains(["MySQL"])), via: .categories["CMS"], tech_count: .meta.tech_count}'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"domain"&lt;/span&gt;: &lt;span class="s2"&gt;"example-store.com"&lt;/span&gt;,
&lt;span class="s2"&gt;"mysql"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
&lt;span class="s2"&gt;"via"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WordPress"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"tech_count"&lt;/span&gt;: 14
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When all you need is the boolean, the &lt;code&gt;/check&lt;/code&gt; endpoint is the cheapest call—pass the domain and &lt;code&gt;tech=mysql&lt;/code&gt; (the parameter is case-insensitive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/check?url=wordpress.org&amp;amp;tech=mysql"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"domain"&lt;/span&gt;: &lt;span class="s2"&gt;"wordpress.org"&lt;/span&gt;,
&lt;span class="s2"&gt;"technology"&lt;/span&gt;: &lt;span class="s2"&gt;"MySQL"&lt;/span&gt;,
&lt;span class="s2"&gt;"detected"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100,
&lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Databases"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"response_ms"&lt;/span&gt;: 1204,
&lt;span class="s2"&gt;"cached"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scaling Up with POST /analyze/batch
&lt;/h3&gt;

&lt;p&gt;For list building, &lt;code&gt;POST /analyze/batch&lt;/code&gt; accepts up to 10 URLs per request and analyzes them concurrently. Here is a complete pipeline using &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and &lt;code&gt;jq&lt;/code&gt; that reads &lt;code&gt;domains.txt&lt;/code&gt; (one domain per line) and writes every MySQL-confirmed domain to &lt;code&gt;mysql_leads.csv&lt;/code&gt;, annotated with the platform that implied the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# find-mysql.sh — filter a domain list down to MySQL-confirmed leads&lt;/span&gt;
&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"detectzestack.p.rapidapi.com"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain,platform,tech_count"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mysql_leads.csv

&lt;span class="c"&gt;# Process domains.txt in batches of 10 (the /analyze/batch maximum)&lt;/span&gt;
xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 10 &amp;lt; domains.txt | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; batch&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nv"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="nv"&gt;$batch&lt;/span&gt; | jq &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; | jq &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'{urls: .}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: &lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$urls&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; |
jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.results[]
| select(.result != null)
| select(.result.categories["Databases"] // [] | contains(["MySQL"]))
| [.result.domain,
((.result.categories["CMS"] // .result.categories["Ecommerce"] // ["unknown"])[0]),
(.result.meta.tech_count | tostring)]
| @csv'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; mysql_leads.csv
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; mysql_leads.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 1,000-domain list becomes 100 batch calls. Domains that fail to resolve or time out appear in &lt;code&gt;results[]&lt;/code&gt; with an &lt;code&gt;error&lt;/code&gt; field instead of a &lt;code&gt;result&lt;/code&gt;, and the &lt;code&gt;select(.result != null)&lt;/code&gt; guard skips them cleanly. One more filter worth adding for data quality: check &lt;code&gt;meta.scan_depth&lt;/code&gt;. A value of &lt;code&gt;"partial"&lt;/code&gt; means the HTTP fetch failed and only DNS and TLS layers ran—since MySQL implications come from HTTP-layer platform detection, a partial scan can never find MySQL, and those domains belong in a retry queue rather than your rejects file. For throughput, retries, and a production Python version of this scanner, see &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;how to batch scan 1,000 websites&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Prospect List: From Detection to Outreach
&lt;/h2&gt;

&lt;p&gt;The CSV above is a lead list, but the &lt;code&gt;platform&lt;/code&gt; column is what makes it routable. A MySQL detection via Magento and one via WordPress describe very different companies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WordPress + MySQL&lt;/strong&gt; — could be anything from a hobby blog to an enterprise content site. Qualify further on &lt;code&gt;tech_count&lt;/code&gt; and the rest of the stack: a site also running a tag manager, a CRM widget, and a CDN is a business; fifteen plugins and shared hosting is not your enterprise buyer. Our guide to &lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;checking if a website uses WordPress&lt;/a&gt; covers reading those secondary signals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Magento / Shopware + MySQL&lt;/strong&gt; — transactional databases under real load. These companies feel query latency in revenue and are the natural audience for performance and reliability tooling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted tools (BookStack, MantisBT) + MySQL&lt;/strong&gt; — engineering-led teams that run their own infrastructure and can actually install what you sell.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comparing Two Prospects with POST /compare
&lt;/h3&gt;

&lt;p&gt;When you are deciding which of two accounts to work first, &lt;code&gt;POST /compare&lt;/code&gt; analyzes 2–10 domains in one call and computes the shared and unique technologies across them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/compare"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["prospect-a.com", "prospect-b.com"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'{shared, unique_a: .domains[0].unique, unique_b: .domains[1].unique}'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"shared"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WordPress"&lt;/span&gt;, &lt;span class="s2"&gt;"MySQL"&lt;/span&gt;, &lt;span class="s2"&gt;"PHP"&lt;/span&gt;, &lt;span class="s2"&gt;"Nginx"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"unique_a"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"WooCommerce"&lt;/span&gt;, &lt;span class="s2"&gt;"Cloudflare"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"unique_b"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HubSpot"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both prospects run WordPress on MySQL, but prospect A added ecommerce (WooCommerce)—its database is taking orders, not just serving pages. If you sell backup or performance tooling, A goes to the top of the queue. The full response also carries each domain’s complete &lt;code&gt;technologies&lt;/code&gt; array, so one compare call doubles as two enrichment calls. Feeding these signals into a scoring model is covered in our &lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;lead enrichment pipeline guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  MySQL Detection vs Other Technographic Tools
&lt;/h2&gt;

&lt;p&gt;Every external technographic tool—ours included—detects databases the same way, because there is only one way: implication through the application layer. The differences that actually matter when you evaluate tools for a MySQL pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live scans vs stored indexes.&lt;/strong&gt; Directory-style tools answer from a crawl that may be months old; a site that migrated off Magento last quarter still shows as a MySQL lead. DetectZeStack scans the domain at request time, so the detection reflects today’s stack. (Results are cached briefly for repeat lookups—the &lt;code&gt;cached&lt;/code&gt; field in every response tells you which you got.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured output.&lt;/strong&gt; A boolean from &lt;code&gt;/check&lt;/code&gt;, a filterable &lt;code&gt;categories&lt;/code&gt; map from &lt;code&gt;/analyze&lt;/code&gt;, and CPE identifiers on every detection that has one—built for scripts rather than screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost at list-building volume.&lt;/strong&gt; Enterprise technographic platforms price for sales teams buying exports. If what you need is “run my own domain list through a detector,” API pricing is an order of magnitude cheaper—we did the math in our &lt;a href="https://detectzestack.com/blog/technographic-data-pricing" rel="noopener noreferrer"&gt;technographic data pricing breakdown&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion and Next Steps
&lt;/h2&gt;

&lt;p&gt;Finding companies using MySQL means accepting how database detection really works: there is no direct fingerprint, only implication through platforms like WordPress, Magento, PrestaShop, and OpenCart that cannot run without it. That gives you high-precision positives (the implication is definitional), negatives that are really unknowns (custom apps hide their database), and one structural blind spot (MySQL vs MariaDB is indistinguishable from outside).&lt;/p&gt;

&lt;p&gt;The pipeline itself is three calls: &lt;code&gt;/demo&lt;/code&gt; or &lt;code&gt;/check&lt;/code&gt; to validate the approach on domains you know, &lt;code&gt;/analyze/batch&lt;/code&gt; to turn a raw domain list into a platform-annotated MySQL lead list, and &lt;code&gt;/compare&lt;/code&gt; to rank the prospects you are about to work. The free tier’s 100 requests per month are enough to validate the pipeline on a sample of your list before scaling up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-nginx" rel="noopener noreferrer"&gt;How to Find Companies Using Nginx&lt;/a&gt; — The same prospecting pipeline at the web-server layer, where detection is direct&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-wordpress" rel="noopener noreferrer"&gt;How to Find Companies Using WordPress&lt;/a&gt; — The platform behind most MySQL detections, as its own prospecting filter&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Find Companies Using Stripe: Technographic Prospecting&lt;/a&gt; — Payment-stack targeting with the same batch workflow&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;How to Check if a Website Uses WordPress&lt;/a&gt; — Reading the platform signals that imply the database&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Deep dive on /analyze/batch throughput, retries, and a Python scanner&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/cpe-identifiers-explained-for-security-teams" rel="noopener noreferrer"&gt;CPE Identifiers Explained for Security Teams&lt;/a&gt; — Mapping detected technologies to vulnerability data&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>DNS Lookup API: MX, NS, SPF, DMARC via REST (2026)</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Sat, 06 Jun 2026 14:01:20 +0000</pubDate>
      <link>https://dev.to/detectzestack/dns-lookup-api-mx-ns-spf-dmarc-via-rest-2026-28fe</link>
      <guid>https://dev.to/detectzestack/dns-lookup-api-mx-ns-spf-dmarc-via-rest-2026-28fe</guid>
      <description>&lt;p&gt;Most engineers default to &lt;code&gt;dig&lt;/code&gt; when they need to look at a domain's DNS. It's fast, it's local, and it's correct. But the moment you need DNS records inside a script, a webhook handler, a CI pipeline, a Slack bot, or a lead-enrichment job, parsing &lt;code&gt;dig&lt;/code&gt;'s text output becomes a chore. A DNS lookup API gives you the same answers as structured JSON: one HTTP call, one parser, every record type in one shot.&lt;/p&gt;

&lt;p&gt;This post walks through what a DNS lookup API does, which records the DetectZeStack &lt;code&gt;GET /dns&lt;/code&gt; endpoint returns, how the email-security grading on top of those records works, and where it beats the shell-out-to-dig pattern. Every example uses the real API; none of the field names are invented.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a DNS Lookup API Does (and Why You Need One)
&lt;/h2&gt;

&lt;p&gt;DNS is the connective tissue of the public internet. Every domain answers questions about itself through DNS: where its web servers live (A, AAAA), where its mail goes (MX), who can sign for it (NS, SOA), what the apex is aliased to (CNAME), and what arbitrary metadata the owner has chosen to publish (TXT — including SPF, DMARC, Google Search Console verification, and dozens of other conventions).&lt;/p&gt;

&lt;p&gt;A DNS lookup API exists because the data is useful in places where running &lt;code&gt;dig&lt;/code&gt; isn't practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A serverless function that needs to know a prospect's email provider before deciding which outreach template to send&lt;/li&gt;
&lt;li&gt;A change-monitoring job that polls a domain every week and posts to Slack when its nameservers move&lt;/li&gt;
&lt;li&gt;A CRM enrichment hook that wants the &lt;code&gt;email_security_grade&lt;/code&gt; for a domain at lead-creation time&lt;/li&gt;
&lt;li&gt;An M&amp;amp;A diligence dashboard that audits 200 portfolio companies' SPF and DMARC posture nightly&lt;/li&gt;
&lt;li&gt;A browser-side tool that can't make raw DNS queries because the browser only speaks HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In all of those, you don't want to package &lt;code&gt;dig&lt;/code&gt; as a dependency, parse its text output, handle stderr, and figure out which selectors to probe for DKIM. You want JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Records You Can Query: A, AAAA, MX, NS, TXT, SOA, CNAME, PTR
&lt;/h2&gt;

&lt;p&gt;The DetectZeStack &lt;code&gt;GET /dns&lt;/code&gt; endpoint resolves all of the standard public DNS record types in a single call. The response is a JSON object with one field per record type:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;IPv4 address records (list of strings)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aaaa&lt;/td&gt;
&lt;td&gt;IPv6 address records (list of strings)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cname&lt;/td&gt;
&lt;td&gt;Canonical name (string; empty when not present at the queried label)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mx&lt;/td&gt;
&lt;td&gt;Mail exchange records as {host, priority} objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ns&lt;/td&gt;
&lt;td&gt;Authoritative nameservers (list of strings)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;txt&lt;/td&gt;
&lt;td&gt;All TXT records (list of strings, including SPF and verification tokens)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;soa&lt;/td&gt;
&lt;td&gt;Start-of-authority record with primary_ns, admin_email, serial, refresh, retry, expire, min_ttl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ptr&lt;/td&gt;
&lt;td&gt;Reverse DNS for the first A record (list of strings)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;email_provider&lt;/td&gt;
&lt;td&gt;Identified email provider from MX records (Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dns_provider&lt;/td&gt;
&lt;td&gt;Identified DNS provider from NS records (Cloudflare, Route 53, Google Cloud DNS, GoDaddy, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;query_ms&lt;/td&gt;
&lt;td&gt;Total DNS resolution time in milliseconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;response_ms&lt;/td&gt;
&lt;td&gt;End-to-end API response time in milliseconds (top-level)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The endpoint sets a 5-second hard cap on a single lookup. If a record type can't be resolved (typical for AAAA on IPv4-only domains, or PTR when no rDNS is published), the field is returned as an empty array rather than as an error — you get all the records that exist in one call instead of having to retry for each missing type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email Security Records: SPF, DMARC, DKIM
&lt;/h2&gt;

&lt;p&gt;SPF and DMARC are plain TXT records. DKIM is a TXT record at a &lt;code&gt;&amp;lt;selector&amp;gt;._domainkey.&amp;lt;domain&amp;gt;&lt;/code&gt; label. If you only ask DNS for them, you get raw strings — &lt;code&gt;v=spf1 include:_spf.google.com ~all&lt;/code&gt;, &lt;code&gt;v=DMARC1; p=reject; rua=mailto:dmarc@...&lt;/code&gt; — and then you have to parse them yourself.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;/dns&lt;/code&gt; endpoint parses them for you and adds them as separate top-level fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;spf&lt;/code&gt; — the parsed SPF record with &lt;code&gt;record&lt;/code&gt;, &lt;code&gt;exists&lt;/code&gt;, &lt;code&gt;mechanism&lt;/code&gt; (&lt;code&gt;-all&lt;/code&gt; / &lt;code&gt;~all&lt;/code&gt; / &lt;code&gt;?all&lt;/code&gt; / &lt;code&gt;+all&lt;/code&gt;), &lt;code&gt;includes&lt;/code&gt; (list of include domains), a letter &lt;code&gt;grade&lt;/code&gt;, and a list of &lt;code&gt;issues&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dmarc&lt;/code&gt; — the parsed DMARC record with &lt;code&gt;record&lt;/code&gt;, &lt;code&gt;exists&lt;/code&gt;, &lt;code&gt;policy&lt;/code&gt; (&lt;code&gt;reject&lt;/code&gt; / &lt;code&gt;quarantine&lt;/code&gt; / &lt;code&gt;none&lt;/code&gt;), &lt;code&gt;subdomain_policy&lt;/code&gt;, aggregate reporting URI (&lt;code&gt;rua&lt;/code&gt;), forensic URI (&lt;code&gt;ruf&lt;/code&gt;), &lt;code&gt;grade&lt;/code&gt;, and &lt;code&gt;issues&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dkim&lt;/code&gt; — the DKIM probe result: which selector was tested (&lt;code&gt;selector_tested&lt;/code&gt;), whether a record &lt;code&gt;exists&lt;/code&gt;, a &lt;code&gt;grade&lt;/code&gt;, and any &lt;code&gt;issues&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How DetectZeStack Grades Email Security
&lt;/h3&gt;

&lt;p&gt;Each protocol gets an A–F letter grade, and an overall &lt;code&gt;email_security_grade&lt;/code&gt; is computed from the three. The logic, briefly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SPF&lt;/strong&gt; — An A requires &lt;code&gt;-all&lt;/code&gt; (hardfail) and fewer than 10 DNS-lookup includes (RFC 7208 caps SPF at 10 lookups). &lt;code&gt;~all&lt;/code&gt; (softfail) scores a B. Missing or &lt;code&gt;+all&lt;/code&gt; is an F.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DMARC&lt;/strong&gt; — &lt;code&gt;p=reject&lt;/code&gt; with &lt;code&gt;rua&lt;/code&gt; reporting earns an A. &lt;code&gt;p=quarantine&lt;/code&gt; is a B. &lt;code&gt;p=none&lt;/code&gt; (monitor-only) is a C. No record is an F.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DKIM&lt;/strong&gt; — The API probes 8 common selectors: &lt;code&gt;google&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;selector1&lt;/code&gt;, &lt;code&gt;selector2&lt;/code&gt;, &lt;code&gt;k1&lt;/code&gt;, &lt;code&gt;mandrill&lt;/code&gt;, &lt;code&gt;mailchimp&lt;/code&gt;, &lt;code&gt;smtp&lt;/code&gt;. If any selector returns a valid record, DKIM grades A. None found grades F.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The composite &lt;code&gt;email_security_grade&lt;/code&gt; is dragged down by the weakest of the three. A single F on any one of SPF, DMARC, or DKIM stops the overall grade from being an A. The &lt;code&gt;email_security_summary&lt;/code&gt; field is a human-readable sentence you can drop straight into a Slack message or a CRM note.&lt;/p&gt;

&lt;p&gt;If you want the full breakdown of SPF/DMARC/DKIM checks beyond what's in this post, see &lt;a href="https://detectzestack.com/blog/dns-intelligence-api-spf-dkim-dmarc" rel="noopener noreferrer"&gt;DNS Intelligence API: SPF, DKIM &amp;amp; DMARC Check&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Lookup API vs Running &lt;code&gt;dig&lt;/code&gt; Yourself
&lt;/h2&gt;

&lt;p&gt;Both approaches resolve the same records. The difference is everything that surrounds the resolution:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;dig / nslookup&lt;/th&gt;
&lt;th&gt;DetectZeStack /dns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One record type per command&lt;/td&gt;
&lt;td&gt;Yes — dig MX, dig TXT, dig NS separately&lt;/td&gt;
&lt;td&gt;All record types in one call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output format&lt;/td&gt;
&lt;td&gt;Text (zone-file style)&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email-provider identification&lt;/td&gt;
&lt;td&gt;Read MX records, classify by hand&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS-provider identification&lt;/td&gt;
&lt;td&gt;Read NS records, classify by hand&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SPF parsing &amp;amp; grading&lt;/td&gt;
&lt;td&gt;Manual (read TXT, interpret)&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DMARC parsing &amp;amp; grading&lt;/td&gt;
&lt;td&gt;Manual (dig _dmarc. TXT)&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DKIM probing&lt;/td&gt;
&lt;td&gt;Guess selectors, query each&lt;/td&gt;
&lt;td&gt;8 common selectors probed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works from browser / serverless&lt;/td&gt;
&lt;td&gt;No (needs OS DNS client)&lt;/td&gt;
&lt;td&gt;Yes (just HTTP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch automation&lt;/td&gt;
&lt;td&gt;Bash + xargs + parsing&lt;/td&gt;
&lt;td&gt;Plain HTTP requests in any language&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; is the right tool when you're sitting at a terminal debugging one domain. The API is the right tool when the answer needs to flow into another system — a Slack alert, a Postgres row, a Notion page, a CRM enrichment field, a CI assertion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the DetectZeStack /dns Endpoint (curl example)
&lt;/h2&gt;

&lt;p&gt;Grab a free RapidAPI key from &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;the DetectZeStack listing&lt;/a&gt; (no credit card required, 100 requests per month on the free plan), then call &lt;code&gt;/dns&lt;/code&gt; with a &lt;code&gt;domain&lt;/code&gt; query parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/dns?domain=stripe.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you just want to see the shape of the response without an API key, the public &lt;code&gt;/demo&lt;/code&gt; endpoint returns the same kind of structured data for the tech-detection side of the API (no key required). You can use it as a smoke test before wiring up your real key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=https://stripe.com"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That call returns the technology-detection response shape:&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;"url"&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://stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React is an open-source JavaScript library for building user interfaces."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://reactjs.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare"&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;"CDN"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare is a global CDN and DDoS-mitigation network."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://www.cloudflare.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CloudFlare.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"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="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"JavaScript frameworks"&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;"React"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"CDN"&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;"Cloudflare"&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;"meta"&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tech_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scan_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1842&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;Use &lt;code&gt;/demo&lt;/code&gt; to confirm the auth-free flow works, then point at &lt;code&gt;/dns&lt;/code&gt; with your key for the DNS-specific records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample JSON Response
&lt;/h3&gt;

&lt;p&gt;A realistic &lt;code&gt;/dns&lt;/code&gt; response looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"a"&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;"185.166.143.26"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"185.166.143.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;"aaaa"&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;"cname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"mx"&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="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aspmx.l.google.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"priority"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alt1.aspmx.l.google.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alt2.aspmx.l.google.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"ns"&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;"ns-cloud-a1.googledomains.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"ns-cloud-a2.googledomains.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"ns-cloud-a3.googledomains.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"ns-cloud-a4.googledomains.com."&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;"txt"&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;"v=spf1 include:_spf.google.com include:servers.mcsv.net ~all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"google-site-verification=..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"MS=ms..."&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;"soa"&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;"primary_ns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ns-cloud-a1.googledomains.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"admin_email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloud-dns-hostmaster.google.com."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"refresh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"retry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"expire"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1209600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"min_ttl"&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;span class="nl"&gt;"ptr"&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;"185-166-143-26.example.ptr."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"email_provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Google Workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"dns_provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Google Cloud DNS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"spf"&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;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v=spf1 include:_spf.google.com include:servers.mcsv.net ~all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"exists"&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;"mechanism"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"includes"&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;"_spf.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"servers.mcsv.net"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"grade"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"issues"&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;"Uses ~all (softfail) instead of -all (hardfail)"&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;"dmarc"&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;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v=DMARC1; p=reject; rua=mailto:dmarc@stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"exists"&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;"policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"subdomain_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"rua"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mailto:dmarc@stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"ruf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"grade"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"issues"&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;"dkim"&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;"selector_tested"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"exists"&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;"grade"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"issues"&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;"email_security_grade"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"email_security_summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Strong email security posture. SPF, DMARC, and DKIM are all configured."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"query_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;168&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;blockquote&gt;
&lt;p&gt;One request, full DNS picture. Every record type, parsed email-auth records, identified providers, and a composite security grade — in a single JSON document.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Common Use Cases: Migration, Deliverability, Lead Enrichment, Monitoring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Pre-migration audit
&lt;/h3&gt;

&lt;p&gt;Before pointing a domain at a new email host or DNS provider, dump the current state so the rollback path is documented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/dns?domain=acme.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: &lt;/span&gt;&lt;span class="nv"&gt;$RAPIDAPI_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'{
ns,
mx,
spf: .spf.record,
dmarc: .dmarc.record,
email_provider,
dns_provider
}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pre-migration.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the same call after the cutover and &lt;code&gt;diff&lt;/code&gt; the two snapshots. If &lt;code&gt;email_provider&lt;/code&gt; stays the same when you expected it to change, you know propagation hasn't completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deliverability triage
&lt;/h3&gt;

&lt;p&gt;When a sales team reports "our emails are going to spam", the first three things to check are SPF, DMARC, and DKIM. One curl call surfaces all three plus a grade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/dns?domain=&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: &lt;/span&gt;&lt;span class="nv"&gt;$RAPIDAPI_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'{grade: .email_security_grade, summary: .email_security_summary,
spf: .spf.grade, dmarc: .dmarc.policy, dkim: .dkim.exists}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Lead enrichment
&lt;/h3&gt;

&lt;p&gt;For B2B sales, the email provider and DNS provider tell you a lot about company size and IT sophistication. A small business on GoDaddy DNS with no DMARC is a very different conversation from an enterprise on Cloudflare with &lt;code&gt;p=reject&lt;/code&gt;. Hook the &lt;code&gt;/dns&lt;/code&gt; call into the new-lead webhook in your CRM and write &lt;code&gt;email_provider&lt;/code&gt;, &lt;code&gt;dns_provider&lt;/code&gt;, and &lt;code&gt;email_security_grade&lt;/code&gt; onto the lead record. For the broader pipeline pattern, see &lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Infrastructure-change monitoring
&lt;/h3&gt;

&lt;p&gt;Run a daily cron that compares today's MX, NS, and SPF to yesterday's. Any diff triggers a Slack alert. This is how you catch "marketing changed our ESP and broke SPF" before customer support catches it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# /opt/scripts/dns-watch.sh — daily cron, 0 8 * * *&lt;/span&gt;
&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yourdomain.com"&lt;/span&gt;
&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/dns-watch/&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;
&lt;span class="nv"&gt;PREV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.prev"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREV&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/dns?domain=&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: &lt;/span&gt;&lt;span class="nv"&gt;$RAPIDAPI_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'{mx, ns, spf: .spf.record, dmarc: .dmarc.record, grade: .email_security_grade}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREV&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; diff &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREV&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
&lt;/span&gt;&lt;span class="nv"&gt;DIFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;diff &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREV&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-40&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SLACK_WEBHOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;DNS change detected for &lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\n\`\`\`&lt;/span&gt;&lt;span class="nv"&gt;$DIFF&lt;/span&gt;&lt;span class="se"&gt;\`\`\`\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DNS isn't only an email signal — CDN and hosting providers also leak through. For that angle see &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;Detect CDN &amp;amp; Hosting Provider&lt;/a&gt; and &lt;a href="https://detectzestack.com/blog/dns-based-technology-detection" rel="noopener noreferrer"&gt;DNS-Based Technology Detection&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing and Rate Limits
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Requests/Month&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Typical fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic (free)&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;$0/mo&lt;/td&gt;
&lt;td&gt;Personal audits, weekly checks on a few domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;$9/mo&lt;/td&gt;
&lt;td&gt;Small MSP, daily monitoring of 20–30 domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultra&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;$29/mo&lt;/td&gt;
&lt;td&gt;Lead enrichment at modest volume, agency portfolios&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mega&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;td&gt;$79/mo&lt;/td&gt;
&lt;td&gt;Vendor-risk programs, large-scale CRM enrichment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Quota is shared across endpoints: &lt;code&gt;/dns&lt;/code&gt;, &lt;code&gt;/analyze&lt;/code&gt;, &lt;code&gt;/certificate/check&lt;/code&gt;, and &lt;code&gt;/security&lt;/code&gt; all draw from the same monthly bucket. A daily check on 3 domains is ~90 requests/month — comfortably inside the free tier.&lt;/p&gt;

&lt;p&gt;For SSL alongside DNS monitoring, pair this with &lt;a href="https://detectzestack.com/blog/ssl-certificate-check-api-devops" rel="noopener noreferrer"&gt;the SSL Certificate Check API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started in 60 Seconds
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at &lt;a href="https://rapidapi.com/mlugoapx/api/detectzestack" rel="noopener noreferrer"&gt;rapidapi.com/mlugoapx/api/detectzestack&lt;/a&gt; and copy your &lt;code&gt;x-rapidapi-key&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the curl example above with a domain you control.&lt;/li&gt;
&lt;li&gt;Read &lt;code&gt;email_security_grade&lt;/code&gt; first — if it's not an A, the rest of the response tells you exactly which protocol pulled it down.&lt;/li&gt;
&lt;li&gt;If you only want a smoke test with no signup, hit &lt;code&gt;https://detectzestack.com/demo?url=https://example.com&lt;/code&gt; — same response shape (for tech detection), no key needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/dns-intelligence-api-spf-dkim-dmarc" rel="noopener noreferrer"&gt;DNS Intelligence API: SPF, DKIM &amp;amp; DMARC Check&lt;/a&gt; — Deep dive on how the email-security grading works&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/dns-based-technology-detection" rel="noopener noreferrer"&gt;DNS-Based Technology Detection&lt;/a&gt; — How DNS records expose CDNs, hosting providers, and infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;Detect CDN &amp;amp; Hosting Provider&lt;/a&gt; — CDN identification via DNS + HTTP signals&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/ssl-certificate-check-api-devops" rel="noopener noreferrer"&gt;SSL Certificate Check API for DevOps Teams&lt;/a&gt; — Cert expiry, chain, and TLS posture as a sibling endpoint&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/ssl-monitoring-api" rel="noopener noreferrer"&gt;SSL Monitoring API: Cert Expiry, Issuer &amp;amp; Chain&lt;/a&gt; — Cron + Slack alerting patterns&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/lead-enrichment-pipeline-with-tech-detection" rel="noopener noreferrer"&gt;Lead Enrichment Pipeline with Tech Detection&lt;/a&gt; — Wiring DNS + tech signals into a CRM&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>StackShare Alternative: Programmatic Tech Stack Research API</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Sun, 17 May 2026 14:01:11 +0000</pubDate>
      <link>https://dev.to/detectzestack/stackshare-alternative-programmatic-tech-stack-research-api-2dc0</link>
      <guid>https://dev.to/detectzestack/stackshare-alternative-programmatic-tech-stack-research-api-2dc0</guid>
      <description>&lt;p&gt;StackShare was the place engineers went to peek at another company’s stack. You typed in a name, got a profile page, and saw the libraries and services that engineering team had decided to publicly share. For a long time it was the closest thing to a public registry of who was running what.&lt;/p&gt;

&lt;p&gt;It still has profile pages. What it doesn’t have, in any practical sense, is a programmatic API you can hit from a CRM workflow, a research notebook, or a sales-ops pipeline. The public StackShare API was deprecated, third-party access went quiet, and the experience now is “browse a UI” rather than “loop over a list of domains.” If your job-to-be-done is “tell my software what stack a company is running,” StackShare isn’t the right shape for it anymore.&lt;/p&gt;

&lt;p&gt;This guide covers why people end up looking for a StackShare alternative, what a programmatic tech stack research API actually needs to do, and how the tradeoffs shake out across the realistic options. The example at the end is a working &lt;code&gt;curl&lt;/code&gt; against a free endpoint — you can run it in 30 seconds and decide for yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Look for a StackShare Alternative
&lt;/h2&gt;

&lt;p&gt;Three concrete reasons surface again and again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No accessible public API.&lt;/strong&gt; StackShare’s API access has effectively wound down for general developer use. You can browse profiles in a browser, but stitching that data into a workflow means scraping a UI — brittle, slow, and against the terms most public sites set. For a research workflow or a CRM enrichment job, that’s a non-starter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crowdsourced data goes stale.&lt;/strong&gt; Profiles on StackShare are filled in by engineers at the company, often once, often years ago. A team that filed their stack in 2021 might be on a completely different setup now — new framework, different CDN, replaced analytics, dropped feature flags. The profile doesn’t know.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage is patchy.&lt;/strong&gt; Big-name SaaS companies have profiles. The mid-market SaaS company you’re prospecting into often does not. For sales research and lead enrichment workflows, the long tail is where the value is — and that’s where StackShare thins out the most.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of those bites you, what you actually want is a tech detection API: something you give a domain to, and it tells you, right now, what that domain is running. The next sections walk through what StackShare offers, where the gap is, and how a programmatic alternative covers it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What StackShare Offers (and What’s Missing)
&lt;/h2&gt;

&lt;p&gt;StackShare’s product is a community wiki for tech stacks. Engineers create a profile for their company, list the tools and services they use, and tag categories. The site aggregates those entries into directories — “everyone using Postgres,” “all sites running Stripe,” and so on — and surfaces popularity trends and comparisons between similar tools.&lt;/p&gt;

&lt;p&gt;That model has real strengths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editorial framing.&lt;/strong&gt; Profiles include a why, not just a what. Why a team picked PostgreSQL over MySQL, why they switched analytics tools. That context is rare in any other source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Categories of tools detection alone misses.&lt;/strong&gt; Internal tools, project management software, CI/CD platforms, design tools — things that don’t leave a fingerprint on the public website. A self-reported profile knows the team uses Linear and GitHub Actions; a website scanner does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery and trends.&lt;/strong&gt; “What are all the alternatives to Segment?” is a question StackShare is genuinely good at, because the data is structured around tools rather than companies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The API Gap
&lt;/h3&gt;

&lt;p&gt;What StackShare doesn’t do well in 2026 is programmatic access. The public API that existed in earlier years isn’t generally available now, and there’s no documented self-serve replacement aimed at developers who want to enrich a list of 5,000 domains. So the data exists, but it sits behind a UI you have to click through. For workflows where automation is the whole point, that’s the missing piece.&lt;/p&gt;

&lt;p&gt;The other gap is freshness. Detection from an actual scan tells you what a website is doing today. A profile that was last updated in 2022 tells you what an engineer remembered to type in three years ago. For competitive intelligence, lead enrichment, and stack monitoring, you need today.&lt;/p&gt;

&lt;h2&gt;
  
  
  DetectZeStack as a Programmatic StackShare Alternative
&lt;/h2&gt;

&lt;p&gt;DetectZeStack is a focused REST API for live tech stack detection. Give it a domain, get back the technologies running on the public-facing site — JavaScript frameworks, CMS, analytics, CDN, hosting, payment processors, marketing tools, web server, security headers, and more. There’s no community wiki, no profile editing, no UI to curate. The product is the API.&lt;/p&gt;

&lt;p&gt;The free tier on RapidAPI is 100 requests/month with no credit card. Paid tiers scale linearly: $9/mo for 1,000 requests, $29/mo for 10,000, $79/mo for 50,000. API access is on every tier — the free tier and the top tier hit the exact same endpoints with the exact same response shape.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Detection vs Crowdsourced Profiles
&lt;/h3&gt;

&lt;p&gt;Every &lt;code&gt;/analyze&lt;/code&gt; call performs a real scan against the target domain. There’s no static profile to go stale, no cached community entry. If a company switched their CDN from Fastly to Cloudflare last week, the next scan reflects that. If they swapped React for Svelte, the next scan reflects that.&lt;/p&gt;

&lt;p&gt;That comes with a tradeoff worth being honest about: detection only sees what’s on the public site. Internal tools, build pipelines, communication apps, ticket trackers — none of those leave fingerprints on a marketing page. A self-reported profile catches them; a scan does not. If your research depends on knowing the internal tools side, detection alone won’t replace it. If your research is “what does this company’s public stack look like, programmatically, at scale,” detection wins clearly.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS, SSL, and Security Signals StackShare Doesn’t Cover
&lt;/h3&gt;

&lt;p&gt;DetectZeStack runs three detection layers on every scan, and each detected technology carries a &lt;code&gt;source&lt;/code&gt; field of &lt;code&gt;http&lt;/code&gt;, &lt;code&gt;dns&lt;/code&gt;, or &lt;code&gt;tls&lt;/code&gt; so you can tell which layer surfaced it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP fingerprinting&lt;/strong&gt; against the open-source Wappalyzer signature database (7,500+ patterns) for frameworks, CMS, analytics, ad tech, marketing automation, server software, and much more. This is the same signature corpus that powers &lt;a href="https://detectzestack.com/blog/wappalyzer-open-source-alternatives" rel="noopener noreferrer"&gt;several open-source detection tools&lt;/a&gt;, kept current with regular updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS analysis&lt;/strong&gt; on CNAME and NS records to identify CDNs and hosting providers that don’t advertise themselves in HTTP headers. &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;CDN and hosting detection via DNS&lt;/a&gt; catches Cloudflare in proxy mode, CloudFront, Fastly, Vercel, Netlify, and Akamai even when the upstream &lt;code&gt;Server&lt;/code&gt; header is generic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS inspection&lt;/strong&gt; for certificate authority, HSTS configuration, and TLS-level signals. Useful when an upstream blocks the HTTP fetch but DNS and TLS still produce a partial picture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that exists on a StackShare profile, because none of it is the kind of thing an engineer types into a wiki. It only shows up when you actually scan the domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Example: Pulling a Company’s Tech Stack in One Call
&lt;/h2&gt;

&lt;p&gt;The fastest way to compare a profile-based tool to a detection API is to run the same domain through the API and look at the JSON. The DetectZeStack &lt;code&gt;/demo&lt;/code&gt; endpoint requires no authentication, so you can do this with one &lt;code&gt;curl&lt;/code&gt; right now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=stripe.com"&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response (trimmed for length):&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;"url"&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://stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React is an open-source JavaScript library for building user interfaces."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://reactjs.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare"&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;"CDN"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare is a web-infrastructure and website-security company."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://www.cloudflare.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dns"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stripe"&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;"Payment processors"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stripe is an online payment processing platform for internet businesses."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stripe.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"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="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"CDN"&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;"Cloudflare"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"JavaScript frameworks"&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;"React"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Payment processors"&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;"Stripe"&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;"meta"&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tech_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scan_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1842&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;A few things worth pointing out about the response shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;technologies&lt;/code&gt; is the full list. Each entry has a &lt;code&gt;confidence&lt;/code&gt; score (0–100) and a &lt;code&gt;source&lt;/code&gt; field indicating which detection layer surfaced it. Filter on &lt;code&gt;source: "dns"&lt;/code&gt; when you only want infrastructure signals.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;categories&lt;/code&gt; is a convenience map keyed by category name. Want every payment processor regardless of detection method? Read &lt;code&gt;categories["Payment processors"]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;meta.scan_depth&lt;/code&gt; is &lt;code&gt;"full"&lt;/code&gt; when all three layers ran cleanly. &lt;code&gt;"partial"&lt;/code&gt; means HTTP was blocked but DNS and TLS still produced results.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cached&lt;/code&gt; and &lt;code&gt;response_ms&lt;/code&gt; sit at the top level, not inside &lt;code&gt;meta&lt;/code&gt;. First-time scans typically take 1.5–3 seconds; cached scans return in 5–50ms.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cpe&lt;/code&gt; is populated for technologies that have a CPE 2.3 identifier in the signature database. Feed those straight into NVD for vulnerability lookups — the kind of &lt;a href="https://detectzestack.com/blog/detect-vulnerable-technologies-with-cpe" rel="noopener noreferrer"&gt;CVE pipeline&lt;/a&gt; StackShare profiles can’t support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have an API key, the authenticated endpoint behaves identically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=stripe.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a research workflow that processes a list of domains, the batch endpoint accepts up to 10 URLs in one request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-sX&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["stripe.com", "shopify.com", "vercel.com"]}'&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re scanning thousands of domains, chunk into batches of 10 and run them concurrently from a worker pool. &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;Scanning a thousand domains in one job&lt;/a&gt; covers the rate-limit math and a worker-pool pattern that holds up under real load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Two Companies’ Stacks Programmatically
&lt;/h2&gt;

&lt;p&gt;One of the most common StackShare workflows is “show me the difference between these two companies’ stacks.” DetectZeStack exposes that as a single endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-sX&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/compare"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["stripe.com", "square.com"]}'&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response groups detected technologies into the ones both domains share, the ones unique to each, and the categorical breakdown. That makes it straightforward to power a “how does our stack compare to a competitor’s” tile in a dashboard, or to scan a target list of competitors weekly and alert when the diff changes. &lt;a href="https://detectzestack.com/blog/competitor-website-technology-analysis" rel="noopener noreferrer"&gt;Competitor website technology analysis&lt;/a&gt; walks through the full pattern.&lt;/p&gt;

&lt;p&gt;For change tracking specifically — the “they used to run X, now they run Y” question — the &lt;code&gt;/changes&lt;/code&gt; endpoint returns a feed of detected technology changes from the moment you start scanning a domain regularly. &lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;Tracking website tech changes via API&lt;/a&gt; covers wiring that into a webhook or a daily digest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases: Sales Research, Competitive Intel, and Lead Enrichment
&lt;/h2&gt;

&lt;p&gt;The reasons teams move from “StackShare profiles in a browser” to “detection API in a script” are mostly the same three workflows, in some combination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sales research and prospecting.&lt;/strong&gt; Filter your TAM by what they’re actually running. “Show me every domain in my account list using HubSpot” is a one-liner against the API and a manual click-through against profiles. &lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Technographic prospecting&lt;/a&gt; covers the pattern in detail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRM enrichment.&lt;/strong&gt; Fire a webhook on every new account in your CRM, hit &lt;code&gt;/analyze&lt;/code&gt;, write the technologies back as fields. The hard part is wiring the data flow; the detection itself is one HTTP call. &lt;a href="https://detectzestack.com/blog/tech-stack-enrichment-for-sales-teams" rel="noopener noreferrer"&gt;Tech stack enrichment for sales teams&lt;/a&gt; walks through the integration patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive intelligence.&lt;/strong&gt; Daily scan of a watchlist of competitor domains, surface diffs over time, alert when something material changes. The detection API gives you the raw signal; &lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;a change-tracking pipeline&lt;/a&gt; makes it actionable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those workflows fit well into a profile-page model. They all assume the data is structured, queryable, and current.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When self-reported still wins: If your research depends on internal tools (project management, CI/CD, communication, design), self-reported profiles are still the better source. A scan can’t see Linear or Notion. The right answer is often both — detection for the public stack, profiles or surveys for the internal layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Pricing and Getting Started
&lt;/h2&gt;

&lt;p&gt;Detection-API pricing for tech stack research is published, predictable, and an order of magnitude lower than enterprise sales-intel tools. DetectZeStack’s tiers on RapidAPI:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Requests / Month&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;Trying it, side projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$9&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;Indie tools, small enrichment jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultra&lt;/td&gt;
&lt;td&gt;$29&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;CRM enrichment, dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mega&lt;/td&gt;
&lt;td&gt;$79&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;td&gt;Large account lists, scheduled re-scans&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For comparison, full sales-intelligence platforms that bundle detection with contact databases and firmographic data start in the four-figure-per-month range and require a sales call. &lt;a href="https://detectzestack.com/blog/technographic-data-pricing" rel="noopener noreferrer"&gt;Technographic data pricing&lt;/a&gt; covers why that gap exists across the whole category — the contact data dominates the price, not the detection.&lt;/p&gt;

&lt;p&gt;Getting started is one step: sign up on RapidAPI, copy your key, and call &lt;code&gt;/analyze&lt;/code&gt;. There’s no procurement process, no annual commit. If you’re still deciding, run the &lt;code&gt;/demo&lt;/code&gt; curl above against three or four of the domains you actually care about. The response shape is identical to &lt;code&gt;/analyze&lt;/code&gt; — that single call will tell you whether the detection breadth covers your real workflow before you commit to anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;StackShare is still useful for browsing curated, editorial profiles of well-known engineering teams. What it isn’t, in 2026, is a programmatic source of truth you can plug into automation. For tech stack research that has to scale — CRM enrichment, prospecting, competitive monitoring, change tracking — a live detection API is the right shape.&lt;/p&gt;

&lt;p&gt;If you’re evaluating options for that job, the broader landscape is in the &lt;a href="https://detectzestack.com/blog/best-tech-stack-detection-apis-2026" rel="noopener noreferrer"&gt;2026 detection API roundup&lt;/a&gt;. The &lt;a href="https://detectzestack.com/blog/free-builtwith-alternatives-2026" rel="noopener noreferrer"&gt;free BuiltWith alternatives&lt;/a&gt; guide covers the zero-cost end. And the &lt;a href="https://detectzestack.com/blog/detect-any-website-tech-stack-with-single-api-call" rel="noopener noreferrer"&gt;single API call walkthrough&lt;/a&gt; shows the integration patterns most teams settle on once they decide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/competitor-website-technology-analysis" rel="noopener noreferrer"&gt;Competitor Website Technology Analysis&lt;/a&gt; — Building a competitive-intel pipeline on detection data&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Find Companies Using Stripe (Technographic Prospecting)&lt;/a&gt; — Technology-based prospecting workflow&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/tech-stack-enrichment-for-sales-teams" rel="noopener noreferrer"&gt;Tech Stack Enrichment for Sales Teams&lt;/a&gt; — Wiring detection into your CRM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/best-tech-stack-detection-apis-2026" rel="noopener noreferrer"&gt;Best Tech Stack Detection APIs (2026)&lt;/a&gt; — Full landscape across price tiers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-any-website-tech-stack-with-single-api-call" rel="noopener noreferrer"&gt;Detect Any Website’s Tech Stack With a Single API Call&lt;/a&gt; — End-to-end integration walkthrough&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/similartech-alternative" rel="noopener noreferrer"&gt;SimilarTech Alternative&lt;/a&gt; — Comparison against another sales-intel platform&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/free-builtwith-alternatives-2026" rel="noopener noreferrer"&gt;Free BuiltWith Alternatives (2026)&lt;/a&gt; — Zero-cost detection options&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;Track Website Tech Changes via API&lt;/a&gt; — Building a change-detection pipeline&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/technographic-data-pricing" rel="noopener noreferrer"&gt;Technographic Data Pricing&lt;/a&gt; — Why detection API costs vary by 10x&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;Detect CDN and Hosting Provider&lt;/a&gt; — DNS-layer detection that profile pages miss&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Set Up Webhook Tech Stack Changes Alerts via API</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Sun, 10 May 2026 14:00:36 +0000</pubDate>
      <link>https://dev.to/detectzestack/set-up-webhook-tech-stack-changes-alerts-via-api-4fh9</link>
      <guid>https://dev.to/detectzestack/set-up-webhook-tech-stack-changes-alerts-via-api-4fh9</guid>
      <description>&lt;p&gt;Polling an API on a timer to check whether a website changed its tech stack is wasteful. You burn requests checking domains that have not changed, and you miss changes that happen between your polling intervals. Webhooks solve both problems: DetectZeStack monitors domains on a schedule and pushes notifications to your server only when something actually changes.&lt;/p&gt;

&lt;p&gt;This guide walks through the full webhook lifecycle: creating a subscription, enabling scheduled monitoring, verifying HMAC-signed payloads, and building a working Slack integration that alerts your team when a competitor switches frameworks, adds a CDN, or drops their analytics provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Monitor Websites for Tech Stack Changes
&lt;/h2&gt;

&lt;p&gt;Technology stack changes are leading indicators. A company adding Stripe is about to launch payments. A competitor switching from Heroku to AWS is preparing to scale. A client removing their Content-Security-Policy header just created a security vulnerability nobody noticed.&lt;/p&gt;

&lt;p&gt;Manual checking does not scale. If you are tracking 20 competitor domains, logging in weekly to scan each one is a full hour of repetitive work. And you will miss changes that happen mid-week.&lt;/p&gt;

&lt;p&gt;Webhook alerts flip the model: instead of you checking DetectZeStack, DetectZeStack checks the domains and tells you when something changes. Zero wasted effort, zero missed changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases for Webhook Tech Stack Changes Alerts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Competitive intelligence&lt;/strong&gt; — get notified when a competitor adds Intercom, switches from React to Next.js, or deploys behind Cloudflare&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security monitoring&lt;/strong&gt; — alert when a managed client removes security headers, drops their WAF, or changes SSL configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sales signals&lt;/strong&gt; — identify prospects adding payment processors, marketing automation, or analytics tools that indicate buying intent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investment due diligence&lt;/strong&gt; — track portfolio company infrastructure decisions in real time rather than waiting for quarterly updates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agency client oversight&lt;/strong&gt; — catch unauthorized changes to client websites before they become incidents&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How DetectZeStack Webhook Alerts Work
&lt;/h2&gt;

&lt;p&gt;The webhook system has three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Subscription&lt;/strong&gt; — you register a domain + callback URL pair via &lt;code&gt;POST /webhooks&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt; — you enable daily or weekly scanning via &lt;code&gt;PATCH /webhooks/{id}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delivery&lt;/strong&gt; — when changes are detected, DetectZeStack POSTs a signed payload to your URL&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Webhook Lifecycle
&lt;/h3&gt;

&lt;p&gt;Every time a monitored domain is scanned, DetectZeStack diffs the new snapshot against the previous one. If technologies were added, removed, or changed version, a &lt;code&gt;tech_stack.changed&lt;/code&gt; event is sent to all active subscribers for that domain. If nothing changed, no notification is sent — your endpoint stays quiet.&lt;/p&gt;

&lt;p&gt;Every scan (whether changes were found or not) also fires a &lt;code&gt;tech_stack.analyzed&lt;/code&gt; event with the full technology list. This is useful if you want to log every scan result to your own database regardless of whether anything changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Create a Webhook Subscription
&lt;/h2&gt;

&lt;p&gt;Register a webhook by POSTing the domain you want to monitor and the URL where you want to receive notifications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/webhooks"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
"domain": "competitor.com",
"webhook_url": "https://your-server.com/hooks/techstack"
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&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://your-server.com/hooks/techstack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"hmac_secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;hmac_secret&lt;/code&gt; is returned exactly once at creation time. Store it securely — it cannot be retrieved again. You will use it to verify that incoming webhook deliveries actually came from DetectZeStack.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Webhook URLs must use HTTPS. HTTP endpoints are rejected to prevent credentials from being transmitted in plaintext. The URL must also resolve to a public IP address (no localhost or private ranges).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Webhook Limits by Plan
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Webhook Subscriptions&lt;/th&gt;
&lt;th&gt;Monitoring&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic (free)&lt;/td&gt;
&lt;td&gt;$0/mo&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Not available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$9/mo&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultra&lt;/td&gt;
&lt;td&gt;$29/mo&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mega&lt;/td&gt;
&lt;td&gt;$79/mo&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Free tier users can create webhook subscriptions and receive notifications when they manually trigger scans via the API. Scheduled monitoring (automatic daily or weekly scans) requires a paid tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Enable Scheduled Monitoring
&lt;/h2&gt;

&lt;p&gt;Creating a webhook subscription does not automatically start monitoring. To have DetectZeStack scan the domain on a schedule, update the subscription with a monitoring interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/webhooks/42"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"monitor_interval": "daily"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"updated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"monitor_interval"&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"&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;h3&gt;
  
  
  Daily vs Weekly Monitoring Intervals
&lt;/h3&gt;

&lt;p&gt;Choose the interval based on how time-sensitive the information is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily&lt;/strong&gt; — best for security monitoring, active competitive tracking, or client oversight where you need to catch changes within 24 hours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekly&lt;/strong&gt; — sufficient for investment monitoring, long-term trend tracking, or low-priority domains where day-level granularity is unnecessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To disable monitoring without deleting the webhook, set &lt;code&gt;monitor_interval&lt;/code&gt; to an empty string (&lt;code&gt;""&lt;/code&gt;). The subscription remains active for manual triggers but no automatic scans occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Receive and Verify Webhook Payloads
&lt;/h2&gt;

&lt;p&gt;When changes are detected, DetectZeStack sends an HTTP POST to your registered URL. The request includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Content-Type: application/json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Webhook-Event: tech_stack.analyzed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Webhook-Signature: sha256=&amp;lt;hex-encoded HMAC&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HMAC Signature Verification
&lt;/h3&gt;

&lt;p&gt;Every delivery is signed with your webhook's HMAC secret using SHA-256. To verify:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the raw request body (do not parse JSON first)&lt;/li&gt;
&lt;li&gt;Compute HMAC-SHA256 of the raw body using your stored &lt;code&gt;hmac_secret&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compare the computed signature against the value in &lt;code&gt;X-Webhook-Signature&lt;/code&gt; (after stripping the &lt;code&gt;sha256=&lt;/code&gt; prefix)&lt;/li&gt;
&lt;li&gt;Use constant-time comparison to prevent timing attacks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Python verification example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload_body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Verify the HMAC-SHA256 signature from DetectZeStack webhook.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sha256=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="n"&gt;expected_sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;  &lt;span class="c1"&gt;# strip "sha256=" prefix
&lt;/span&gt;&lt;span class="n"&gt;computed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="n"&gt;payload_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Payload Structure
&lt;/h3&gt;

&lt;p&gt;The webhook payload contains the full scan result along with metadata:&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;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tech_stack.analyzed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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="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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare"&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;"CDN"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"confidence"&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="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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Next.js"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"14.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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="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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Google Analytics"&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;"Analytics"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"confidence"&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="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;"meta"&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;"scan_time_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1842&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"detection_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&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-04-20T10:30:00Z"&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;If the scan detected changes compared to the previous snapshot, the payload additionally includes technology change events in the &lt;code&gt;/changes&lt;/code&gt; feed that you can query separately for structured diffs (added, removed, version_changed).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Delivery retries: If your endpoint returns a non-2xx status code, DetectZeStack retries up to 3 times with exponential backoff (2 seconds, then 4 seconds). After 3 failures, the delivery is abandoned for that event.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4 — Query the Change Feed for Context
&lt;/h2&gt;

&lt;p&gt;Webhook payloads tell you the current state. To see exactly what changed (what was added or removed), query the &lt;code&gt;/changes&lt;/code&gt; endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/changes?domain=competitor.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&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;"changes"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4821&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cloudflare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"added"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&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-04-20T10:30:00Z"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4822&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Akamai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"removed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&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-04-20T10:30:00Z"&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;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"history_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pro"&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;Combining webhooks with the change feed gives you the full picture: the webhook tells you &lt;em&gt;something changed&lt;/em&gt;, and the change feed tells you &lt;em&gt;exactly what&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing Your Webhooks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  List Active Webhooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/webhooks"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&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;"webhooks"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&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://your-server.com/hooks/techstack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"monitor_interval"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&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-04-20T09:00:00Z"&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;"count"&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;h3&gt;
  
  
  Update or Delete a Webhook
&lt;/h3&gt;

&lt;p&gt;Change the monitoring interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/webhooks/42"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"monitor_interval": "weekly"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete a subscription entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/webhooks/42"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-rapidapi-host: detectzestack.p.rapidapi.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deleting a webhook stops all monitoring and future deliveries for that subscription immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Python Example — Slack Alerts on Tech Stack Changes
&lt;/h2&gt;

&lt;p&gt;Here is a complete Flask application that receives DetectZeStack webhooks, verifies the signature, queries the change feed for context, and posts a formatted message to Slack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;WEBHOOK_SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_hmac_secret_from_creation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;RAPIDAPI_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;SLACK_WEBHOOK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://hooks.slack.com/services/YOUR/WEBHOOK/URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hooks/techstack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&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;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_webhook&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="c1"&gt;# Step 1: Verify signature
&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-Webhook-Signature&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="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WEBHOOK_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&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;invalid signature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;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;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Query the change feed for structured diffs
&lt;/span&gt;&lt;span class="n"&gt;headers&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;x-rapidapi-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-host&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;detectzestack.p.rapidapi.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://detectzestack.p.rapidapi.com/changes?domain=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;changes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;changes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;no changes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="c1"&gt;# Step 3: Format and send Slack message
&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;changes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;changes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="n"&gt;prefix&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;added&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;+&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;removed&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;-&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;version_changed&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;~&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;change_type&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;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;technology&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;previous_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;previous_version&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new_version&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*Tech stack change detected on &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:*&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;```
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# limit to 10 changes
&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;
{% raw %}
```&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SLACK_WEBHOOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&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;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sha256=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="n"&gt;computed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;payload_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy this behind HTTPS (using nginx, Caddy, or a platform like Railway) and register the public URL as your webhook endpoint. The entire pipeline — detection, notification, and alerting — runs automatically without any polling or cron jobs on your side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It: Scan a Domain with the Demo Endpoint
&lt;/h2&gt;

&lt;p&gt;Before setting up webhooks, verify what DetectZeStack detects for a given domain using the free demo endpoint (no API key required):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=https://stripe.com"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the full technology list for stripe.com — the same data structure that webhook payloads use. Use this to validate that the domains you plan to monitor produce useful detection results before investing in webhook setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Webhook Limits and Tier Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Pro ($9/mo)&lt;/th&gt;
&lt;th&gt;Ultra ($29/mo)&lt;/th&gt;
&lt;th&gt;Mega ($79/mo)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Webhook subscriptions&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduled monitoring&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;td&gt;Daily / Weekly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change history depth&lt;/td&gt;
&lt;td&gt;7 days&lt;/td&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;90 days&lt;/td&gt;
&lt;td&gt;365 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API requests/month&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HMAC-signed payloads&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retry on failure&lt;/td&gt;
&lt;td&gt;3 attempts&lt;/td&gt;
&lt;td&gt;3 attempts&lt;/td&gt;
&lt;td&gt;3 attempts&lt;/td&gt;
&lt;td&gt;3 attempts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All plans include HMAC signature verification and automatic retry with exponential backoff. The difference between tiers is how many domains you can monitor simultaneously and whether scheduled (automatic) monitoring is available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started with Webhook Tech Stack Changes Alerts
&lt;/h2&gt;

&lt;p&gt;Setting up webhook-based tech stack monitoring takes about five minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get your API key from RapidAPI (free tier includes 5 webhook subscriptions)&lt;/li&gt;
&lt;li&gt;Create a subscription with &lt;code&gt;POST /webhooks&lt;/code&gt; for each domain you want to monitor&lt;/li&gt;
&lt;li&gt;Enable scheduled monitoring with &lt;code&gt;PATCH /webhooks/{id}&lt;/code&gt; (paid tiers)&lt;/li&gt;
&lt;li&gt;Implement signature verification in your webhook handler&lt;/li&gt;
&lt;li&gt;Route notifications to Slack, PagerDuty, email, or your own dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No polling. No cron jobs. No wasted API requests checking domains that have not changed. DetectZeStack handles the scanning, diffing, and notification delivery — you just receive the alerts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;Track Website Tech Changes Over Time via API&lt;/a&gt; — Full guide to /changes, /history, and /webhooks endpoints&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/automate-security-audits-api" rel="noopener noreferrer"&gt;Automate Security Audits with the DetectZeStack API&lt;/a&gt; — Combine webhooks with security header monitoring&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Bulk scanning for initial baseline before enabling webhook monitoring&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/competitor-website-technology-analysis" rel="noopener noreferrer"&gt;Competitor Website Technology Analysis&lt;/a&gt; — Use tech stack data for competitive intelligence&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/monitor" rel="noopener noreferrer"&gt;Technology Change Monitor&lt;/a&gt; — Interactive dashboard for tracking tech stack changes&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>WhatRuns Alternative API: 4 Options for Programmatic Detection</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Fri, 01 May 2026 14:01:10 +0000</pubDate>
      <link>https://dev.to/detectzestack/whatruns-alternative-api-4-options-for-programmatic-detection-8bp</link>
      <guid>https://dev.to/detectzestack/whatruns-alternative-api-4-options-for-programmatic-detection-8bp</guid>
      <description>&lt;p&gt;If you opened this page, you probably went looking for “WhatRuns API” or “WhatRuns API key,” hit a dead end, and started searching for an alternative. That’s the right move—&lt;a href="https://detectzestack.com/blog/whatruns-api-key-alternative" rel="noopener noreferrer"&gt;WhatRuns has no public API&lt;/a&gt;, no key, and no documentation. It is a browser extension, full stop.&lt;/p&gt;

&lt;p&gt;The good news is that the use cases people associate with WhatRuns—identifying JavaScript frameworks, spotting CMS platforms, mapping hosting and CDN providers, enriching lead lists—are well covered by APIs you can hit with &lt;code&gt;curl&lt;/code&gt; in a few seconds. This guide walks through four practical WhatRuns alternative API options, the trade-offs between them, and a working example you can copy and run today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why WhatRuns Has No Public API
&lt;/h2&gt;

&lt;p&gt;WhatRuns’ founder shipped the extension as a free product several years ago and effectively walked away from active development. The extension still works as a manual lookup tool, but the team never published a REST endpoint, never released SDKs, and never documented an authentication flow. The detection logic runs inside the browser, reads page-level signals, and reports back to a private backend the extension uses for its own UI—not for third-party consumption.&lt;/p&gt;

&lt;p&gt;The result: any workflow that needs automated, repeatable tech detection has to look elsewhere. Browser extensions also can’t see the infrastructure layer. They can’t resolve DNS, inspect TLS certificates, or check IP ranges, which means a CDN like CloudFront or Fastly that doesn’t advertise itself in HTTP headers is invisible. &lt;a href="https://detectzestack.com/blog/dns-tls-detection-vs-browser-extensions" rel="noopener noreferrer"&gt;A purpose-built API can see all four layers&lt;/a&gt;, which matters once you start scanning anything beyond a marketing site.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Look for in a WhatRuns Alternative API
&lt;/h2&gt;

&lt;p&gt;Not every detection API solves the same problem. Before picking one, decide what you actually need. Three dimensions matter most.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coverage Across JS, CMS, Hosting, and DNS
&lt;/h3&gt;

&lt;p&gt;WhatRuns is strongest at JavaScript framework and front-end library detection—it surfaces React, Vue, Next.js, jQuery, Tailwind, analytics scripts, and chat widgets reliably. A direct replacement should cover the same categories, plus the infrastructure signals the extension misses. At a minimum, look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript frameworks and libraries&lt;/strong&gt; — &lt;a href="https://detectzestack.com/blog/how-to-detect-react-website" rel="noopener noreferrer"&gt;React&lt;/a&gt;, Vue, Angular, Next.js, Svelte, jQuery, Tailwind CSS, and so on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CMS and e-commerce platforms&lt;/strong&gt; — WordPress, Shopify, Webflow, HubSpot CMS, Drupal, Magento, Squarespace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics and marketing tools&lt;/strong&gt; — Google Analytics, Segment, Mixpanel, Amplitude, HubSpot, Intercom.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting and CDN&lt;/strong&gt; — Cloudflare, CloudFront, Fastly, Vercel, Netlify, Akamai. &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;DNS-level detection&lt;/a&gt; is what separates the API class from the extension class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and TLS&lt;/strong&gt; — HSTS, certificate authority, SSL/TLS configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pricing That Scales With Usage
&lt;/h3&gt;

&lt;p&gt;If you’re scanning ten domains a month, a free tier on RapidAPI is fine. If you’re enriching a 50,000-row CRM export, the per-domain cost dominates. The cheapest providers settle around $9–$29/month for a few thousand requests. The expensive end—BuiltWith’s premium tier—starts at $295/month and is priced for enterprise sales intelligence rather than ad-hoc detection. &lt;a href="https://detectzestack.com/blog/technographic-data-pricing" rel="noopener noreferrer"&gt;Technographic data pricing&lt;/a&gt; varies by an order of magnitude, so check the rate limits and price-per-call before committing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Response Latency and Cache Behavior
&lt;/h3&gt;

&lt;p&gt;A first-time scan of an unfamiliar domain usually costs 1.5–3 seconds because the API has to make an outbound HTTP request, parse the response, run DNS lookups, and complete a TLS handshake. Subsequent scans of the same domain should be near-instant if the provider caches results. Cached responses on DetectZeStack typically return in 5–50ms, which matters when you’re fanning out across hundreds of domains in a job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four WhatRuns Alternative APIs Compared
&lt;/h2&gt;

&lt;p&gt;Here are the four credible options, ordered roughly from easiest-to-start to most-effort-to-run.&lt;/p&gt;

&lt;h3&gt;
  
  
  DetectZeStack
&lt;/h3&gt;

&lt;p&gt;DetectZeStack is a REST API for tech stack detection that combines HTTP fingerprinting (using the Wappalyzer signature database with 7,300+ patterns), DNS CNAME and NS analysis, and TLS certificate inspection. The free tier is 100 requests/month on RapidAPI with no credit card. Paid tiers start at $9/month for 1,000 requests and scale to 50,000 requests at $79/month.&lt;/p&gt;

&lt;p&gt;Endpoints worth knowing about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /analyze&lt;/code&gt; — single URL, full detection across HTTP, DNS, and TLS.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /demo&lt;/code&gt; — same response shape as &lt;code&gt;/analyze&lt;/code&gt;, no API key needed, useful for trying it out.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /analyze/batch&lt;/code&gt; — up to 10 URLs per request for parallel scans.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /compare&lt;/code&gt; — diff two domains to see which technologies are unique to each.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /certificate&lt;/code&gt; — TLS certificate details (issuer, expiry, SANs).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /dns&lt;/code&gt; — raw DNS records (A, AAAA, CNAME, MX, NS, TXT).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Strengths: free tier, no credit card, DNS-layer detection that browser extensions can’t do, version numbers and CPE identifiers when available for vulnerability mapping. Honest weaknesses: smaller historical dataset than BuiltWith’s, no built-in lead-list export.&lt;/p&gt;

&lt;h3&gt;
  
  
  BuiltWith API
&lt;/h3&gt;

&lt;p&gt;BuiltWith is the long-running incumbent. Their detection covers a similar range of categories and includes deep historical data that goes back years—useful if you want to know when a domain switched from Magento to Shopify. The catch is pricing: the entry-level “Basic” API plan starts at $295/month, with higher tiers running into the low four figures. If your use case is sales intelligence on a known list of accounts, the historical depth can pay for itself. For ad-hoc developer use, it’s usually overkill. &lt;a href="https://detectzestack.com/blog/builtwith-vs-whatruns" rel="noopener noreferrer"&gt;BuiltWith versus WhatRuns&lt;/a&gt; covers the deeper comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wappalyzer API
&lt;/h3&gt;

&lt;p&gt;Wappalyzer publishes its detection signatures as open source (MIT license) and runs a paid hosted API on top of them. Pricing starts at around $250/month for the “Lookup” plan with monthly request quotas. The signature database is the same one that powers DetectZeStack and many other tools, so detection breadth is comparable. Wappalyzer’s differentiator is the bundled lead-generation tooling (filtered lists of sites by technology, exportable to CSV).&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Hosted wappalyzergo
&lt;/h3&gt;

&lt;p&gt;If you have engineering capacity and want zero per-call cost, you can run detection in-process. &lt;code&gt;wappalyzergo&lt;/code&gt; is a Go library that ports the Wappalyzer detection logic and ships the same signature JSON. You write a few lines of Go to fetch a URL, hand the response to the library, and read out the technologies. There’s no rate limit, no monthly bill, and no third-party dependency in the request path.&lt;/p&gt;

&lt;p&gt;The trade-offs are real, though. You need to maintain the deployment, update the signature file periodically, build outbound fetch logic with proper SSRF protection, and handle DNS and TLS detection separately because &lt;code&gt;wappalyzergo&lt;/code&gt; only handles HTTP-layer detection. &lt;a href="https://detectzestack.com/blog/wappalyzer-open-source-alternatives" rel="noopener noreferrer"&gt;A deeper walkthrough of the open-source path&lt;/a&gt; covers what to expect in production. This is the right answer when you’re scanning millions of domains and the API bills would be prohibitive; it’s the wrong answer for most teams who just want a result back from one HTTP call.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Free Tier&lt;/th&gt;
&lt;th&gt;Entry Price&lt;/th&gt;
&lt;th&gt;DNS / TLS Detection&lt;/th&gt;
&lt;th&gt;Hosted&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DetectZeStack&lt;/td&gt;
&lt;td&gt;100 req/mo&lt;/td&gt;
&lt;td&gt;$9/mo (1k req)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BuiltWith API&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$295/mo&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wappalyzer API&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$250/mo&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wappalyzergo (self-hosted)&lt;/td&gt;
&lt;td&gt;Free (your infra)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;Build it yourself&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Calling the DetectZeStack API: A Working Example
&lt;/h2&gt;

&lt;p&gt;The fastest way to see whether a detection API meets your needs is to fire one request at it. The DetectZeStack &lt;code&gt;/demo&lt;/code&gt; endpoint requires no authentication, so you can test the response shape before signing up for anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-URL Detection With /analyze
&lt;/h3&gt;

&lt;p&gt;Try &lt;code&gt;/demo&lt;/code&gt; first. Same response shape as &lt;code&gt;/analyze&lt;/code&gt;, no key needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=stripe.com"&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response (trimmed):&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;"url"&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://stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon S3"&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;"CDN"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon S3 or Amazon Simple Storage Service is a service offered by AWS that provides object storage through a web service interface."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://aws.amazon.com/s3/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon S3.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nginx"&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;"Web servers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reverse proxies"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nginx is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://nginx.org/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;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nginx.svg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DigiCert"&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;"SSL/TLS certificate authority"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tls"&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;"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="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"CDN"&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;"Amazon S3"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"PaaS"&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;"Amazon Web Services"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Reverse proxies"&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;"Nginx"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"SSL/TLS certificate authority"&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;"DigiCert"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Security"&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;"HSTS"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Web servers"&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;"Nginx"&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;"meta"&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tech_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"scan_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1842&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;A few things worth noting in the response:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;technologies&lt;/code&gt; is the full list with confidence scores and source labels. The &lt;code&gt;source&lt;/code&gt; field shows how the technology was detected: &lt;code&gt;http&lt;/code&gt; for header or HTML pattern matches, &lt;code&gt;dns&lt;/code&gt; for CNAME/NS matches, and &lt;code&gt;tls&lt;/code&gt; for certificate-based detection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;categories&lt;/code&gt; is a convenience map for “give me everything in CDN” or “give me everything in JavaScript frameworks.”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;meta.scan_depth&lt;/code&gt; is &lt;code&gt;"full"&lt;/code&gt; when all three layers ran, &lt;code&gt;"partial"&lt;/code&gt; when the upstream blocked HTTP requests but DNS or TLS still produced results.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cached&lt;/code&gt; and &lt;code&gt;response_ms&lt;/code&gt; sit at the top level, not inside &lt;code&gt;meta&lt;/code&gt;. Cached responses typically return in 5–50ms.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cpe&lt;/code&gt; is populated when a CPE 2.3 identifier exists for the technology, which is what you feed into NVD for &lt;a href="https://detectzestack.com/blog/detect-vulnerable-technologies-with-cpe" rel="noopener noreferrer"&gt;vulnerability lookups&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have an API key, the same call against the authenticated endpoint looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=stripe.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bulk Scans With /analyze/batch
&lt;/h3&gt;

&lt;p&gt;For workflows that need to scan a list of domains, &lt;code&gt;POST /analyze/batch&lt;/code&gt; handles up to 10 URLs per request and runs the fetches in parallel server-side. That removes the round-trip overhead of issuing ten separate calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-sX&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["stripe.com", "shopify.com", "vercel.com"]}'&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is a &lt;code&gt;results&lt;/code&gt; array with one entry per input URL:&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;"results"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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="err"&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;"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="err"&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;"meta"&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="err"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1842&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shopify.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shopify.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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="err"&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;"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="err"&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;"meta"&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="err"&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;"cached"&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;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vercel.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"result"&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;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vercel.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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="err"&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;"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="err"&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;"meta"&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="err"&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;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"response_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1654&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"total_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1873&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"successful"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="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;If a single URL in the batch fails (for example, an unreachable domain), the corresponding entry will have an &lt;code&gt;error&lt;/code&gt; field instead of a &lt;code&gt;result&lt;/code&gt; field. The successful items still come through, so a partial failure doesn’t blow up the whole job. For larger lists, chunk into batches of 10 and run them concurrently from your worker pool. &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;Scanning a thousand domains&lt;/a&gt; covers the rate-limit math in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating From the WhatRuns Extension to an API Workflow
&lt;/h2&gt;

&lt;p&gt;If you’ve been using WhatRuns by hand—clicking the icon on each page you visit—moving to an API is mostly a rewiring exercise. The shape of the data is similar; what changes is the integration point. A few practical migration tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Map your existing categories.&lt;/strong&gt; WhatRuns groups results into “Frameworks,” “Analytics,” “CMS,” “Web Server,” etc. DetectZeStack uses Wappalyzer’s category names, which are similar but not identical. The &lt;code&gt;categories&lt;/code&gt; object in the response is your lookup table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust confidence scores.&lt;/strong&gt; WhatRuns shows a single technology name with no confidence indicator. APIs return a 0–100 score per detection. For batch jobs, filtering at &lt;code&gt;confidence &amp;gt;= 80&lt;/code&gt; usually removes most false positives without sacrificing real matches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull DNS and TLS results explicitly.&lt;/strong&gt; If you specifically need CDN or hosting provider, don’t rely on the HTTP detection alone—Cloudflare in proxy mode or CloudFront without identifying headers will only show up via DNS or TLS signals. Filter &lt;code&gt;technologies&lt;/code&gt; by &lt;code&gt;source: "dns"&lt;/code&gt; or &lt;code&gt;source: "tls"&lt;/code&gt; when you want infrastructure signals only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache aggressively.&lt;/strong&gt; The API caches responses, but if you’re running daily enrichment over a static account list, store the results in your own warehouse and only refresh weekly. The &lt;code&gt;cached&lt;/code&gt; field tells you whether the response came from cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track changes over time.&lt;/strong&gt; The big upside of moving to an API is that you can record results and diff them. &lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;Tracking technology changes&lt;/a&gt; over time is something WhatRuns simply can’t do because it has no concept of history.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Picking the right tier: If you’re scanning 10–100 domains a month, the free tier covers it. If you’re enriching a CRM with thousands of accounts, the $29/month tier (10,000 requests) is usually the sweet spot. The $79/month tier (50,000 requests) makes sense when you’re running scheduled re-scans across a large account list.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Get Started With a Free API Key
&lt;/h2&gt;

&lt;p&gt;WhatRuns won’t ever ship an API—the project is dormant. But the workflows people associate with WhatRuns translate directly to a detection API, and once you make the switch you get capabilities the extension was structurally incapable of: DNS-layer detection, TLS inspection, batch scans, change tracking, and version-level metadata for vulnerability work.&lt;/p&gt;

&lt;p&gt;If you want to try the closest behavioral match before committing, run the &lt;code&gt;/demo&lt;/code&gt; curl above. It returns the same response shape as the authenticated &lt;code&gt;/analyze&lt;/code&gt; endpoint, costs nothing, and will tell you in one round-trip whether the detection breadth is enough for your use case. For deeper comparisons, see &lt;a href="https://detectzestack.com/blog/detectzestack-vs-whatruns" rel="noopener noreferrer"&gt;DetectZeStack vs WhatRuns&lt;/a&gt; and the broader &lt;a href="https://detectzestack.com/blog/best-tech-stack-detection-apis-2026" rel="noopener noreferrer"&gt;2026 detection API landscape&lt;/a&gt;. To see the full single-call workflow end-to-end, the &lt;a href="https://detectzestack.com/blog/detect-any-website-tech-stack-with-single-api-call" rel="noopener noreferrer"&gt;single API call walkthrough&lt;/a&gt; covers the integration patterns most teams settle on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/whatruns-api-key-alternative" rel="noopener noreferrer"&gt;WhatRuns API Key — There Isn’t One. Here’s the Free Alternative&lt;/a&gt; — Why no key exists and the closest replacement&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detectzestack-vs-whatruns" rel="noopener noreferrer"&gt;DetectZeStack vs WhatRuns&lt;/a&gt; — Side-by-side comparison of detection layers and use cases&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/builtwith-vs-whatruns" rel="noopener noreferrer"&gt;BuiltWith vs WhatRuns&lt;/a&gt; — Historical depth vs lightweight extension trade-off&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/best-tech-stack-detection-apis-2026" rel="noopener noreferrer"&gt;Best Tech Stack Detection APIs (2026)&lt;/a&gt; — Full landscape of detection APIs across price tiers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-any-website-tech-stack-with-single-api-call" rel="noopener noreferrer"&gt;Detect Any Website’s Tech Stack With a Single API Call&lt;/a&gt; — End-to-end integration walkthrough&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/dns-tls-detection-vs-browser-extensions" rel="noopener noreferrer"&gt;DNS + TLS Detection vs Browser Extensions&lt;/a&gt; — What infrastructure signals extensions miss&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/wappalyzer-open-source-alternatives" rel="noopener noreferrer"&gt;Wappalyzer Open-Source Alternatives&lt;/a&gt; — Self-hosted detection with wappalyzergo&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;Batch Scan 1000 Websites&lt;/a&gt; — Rate-limit math and worker pool patterns&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/track-website-tech-changes-api" rel="noopener noreferrer"&gt;Track Website Tech Changes via API&lt;/a&gt; — Building a change-detection pipeline&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/technographic-data-pricing" rel="noopener noreferrer"&gt;Technographic Data Pricing&lt;/a&gt; — Why detection API costs vary by 10x&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Ecommerce Tech Stack Analysis: Shopify vs WooCommerce</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Thu, 23 Apr 2026 14:01:03 +0000</pubDate>
      <link>https://dev.to/detectzestack/ecommerce-tech-stack-analysis-shopify-vs-woocommerce-hck</link>
      <guid>https://dev.to/detectzestack/ecommerce-tech-stack-analysis-shopify-vs-woocommerce-hck</guid>
      <description>&lt;p&gt;Every ecommerce store is built on layers of technology: a platform, a payment processor, a CDN, analytics tools, marketing integrations, and often a JavaScript framework powering the storefront. Understanding what those layers are—and how they differ between competitors—is valuable for sales teams qualifying leads, agencies scoping migration projects, and researchers mapping market trends.&lt;/p&gt;

&lt;p&gt;This guide breaks down the typical tech stacks behind Shopify and WooCommerce stores, explains how to identify custom-built ecommerce platforms, and shows how to automate the analysis using the DetectZeStack API. If you have worked through our &lt;a href="https://detectzestack.com/blog/shopify-vs-woocommerce-detection" rel="noopener noreferrer"&gt;Shopify vs WooCommerce detection&lt;/a&gt; guide, this post goes deeper: beyond just identifying the platform, we analyze the full stack surrounding it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Ecommerce Tech Stack Analysis Matters
&lt;/h2&gt;

&lt;p&gt;Knowing that a store runs on Shopify tells you one thing. Knowing that it also uses Stripe for payments, Cloudflare for its CDN, Klaviyo for email, and Google Analytics 4 for tracking tells you far more. Here are the practical use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sales prospecting&lt;/strong&gt; — A WooCommerce store without a dedicated hosting provider is a prospect for managed WordPress hosting. A Shopify store still using Google Analytics Universal (instead of GA4) may need an analytics migration partner. &lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Technographic prospecting&lt;/a&gt; turns technology signals into qualified leads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive intelligence&lt;/strong&gt; — Map every competitor in a niche to see which payment processors dominate, which CDNs are most common, and whether the market is consolidating around Shopify or staying on WooCommerce. See our &lt;a href="https://detectzestack.com/blog/competitor-website-technology-analysis" rel="noopener noreferrer"&gt;competitor tech analysis guide&lt;/a&gt; for the full methodology.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration planning&lt;/strong&gt; — Agencies migrating stores from WooCommerce to Shopify (or vice versa) need to inventory every plugin, integration, and third-party script before quoting a project. Missing a critical integration means scope creep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security auditing&lt;/strong&gt; — Outdated jQuery versions, exposed PHP headers, and missing security headers are all signals that a technology detection scan can surface. WooCommerce stores in particular inherit the security posture of their hosting environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What a Typical Shopify Tech Stack Looks Like
&lt;/h2&gt;

&lt;p&gt;Shopify is a hosted platform, which means the core infrastructure is managed by Shopify itself. But the technology stack of a Shopify store extends well beyond the platform. Here is what a scan of a typical Shopify store reveals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; Shopify (detected via DNS CNAME to &lt;code&gt;shops.myshopify.com&lt;/code&gt; and &lt;code&gt;cdn.shopify.com&lt;/code&gt; script references)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN:&lt;/strong&gt; Shopify CDN for assets, often with Cloudflare or Fastly in front for the storefront domain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment:&lt;/strong&gt; Stripe (Shopify Payments is built on Stripe), detected via &lt;code&gt;js.stripe.com&lt;/code&gt; script inclusion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics:&lt;/strong&gt; Google Analytics, often alongside Shopify’s built-in analytics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript:&lt;/strong&gt; jQuery (still common in Shopify themes), React (for Hydrogen/headless storefronts)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketing:&lt;/strong&gt; Meta Pixel, Google Tag Manager, Klaviyo&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Payment, CDN, and Analytics on Shopify
&lt;/h3&gt;

&lt;p&gt;Shopify Payments—used by the majority of Shopify stores—is powered by Stripe under the hood. When you scan a Shopify store, you will often see both “Shopify” and “Stripe” in the results. The Stripe detection comes from the &lt;code&gt;js.stripe.com/v3&lt;/code&gt; script tag that Shopify injects into checkout pages.&lt;/p&gt;

&lt;p&gt;For CDN, Shopify serves static assets (images, CSS, JavaScript) from &lt;code&gt;cdn.shopify.com&lt;/code&gt;, which is its own CDN infrastructure. However, many Shopify merchants also use Cloudflare as a reverse proxy in front of their custom domain. In DNS terms, you will see the custom domain CNAME pointing to &lt;code&gt;shops.myshopify.com&lt;/code&gt;, but the nameservers may be Cloudflare’s &lt;code&gt;*.ns.cloudflare.com&lt;/code&gt;. DetectZeStack catches both signals: the Shopify CNAME via DNS detection and the Cloudflare nameservers via NS record inspection.&lt;/p&gt;

&lt;p&gt;Google Analytics is present on the vast majority of Shopify stores. Detection is straightforward: the &lt;code&gt;gtag.js&lt;/code&gt; script or the &lt;code&gt;G-&lt;/code&gt; measurement ID in the page source. Many stores also load Google Tag Manager, which acts as a container for additional tracking scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Typical WooCommerce Tech Stack Looks Like
&lt;/h2&gt;

&lt;p&gt;WooCommerce is a WordPress plugin, so every WooCommerce store is also a WordPress site. This means the tech stack is more varied than Shopify’s because the store owner (or their hosting provider) makes every infrastructure decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; WordPress + WooCommerce (detected via &lt;code&gt;/wp-content/&lt;/code&gt; paths, &lt;code&gt;X-Powered-By: PHP&lt;/code&gt; header, and WooCommerce-specific meta tags)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; Varies widely—from shared hosting to managed WordPress hosts to cloud infrastructure on AWS or DigitalOcean&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN:&lt;/strong&gt; Cloudflare (most common), CloudFront, or a WordPress-specific CDN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment:&lt;/strong&gt; Stripe, PayPal, or both—installed as WooCommerce payment gateway plugins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics:&lt;/strong&gt; Google Analytics (via plugin), sometimes with additional tools like Hotjar or Microsoft Clarity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript:&lt;/strong&gt; jQuery (WordPress ships it by default), sometimes React (for Gutenberg blocks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Wordfence or Sucuri (common WordPress security plugins), Let’s Encrypt TLS certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hosting, Plugins, and Performance Layers
&lt;/h3&gt;

&lt;p&gt;The biggest difference between Shopify and WooCommerce stacks is infrastructure ownership. Shopify handles hosting, scaling, and CDN automatically. WooCommerce store owners must choose and configure each layer themselves.&lt;/p&gt;

&lt;p&gt;This means WooCommerce stores show far more variety in their tech stacks. A scan might reveal Cloudflare CDN on one store, CloudFront on another, and no CDN at all on a third. You can &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;detect the CDN and hosting provider&lt;/a&gt; using DNS CNAME records and HTTP headers, which DetectZeStack checks automatically.&lt;/p&gt;

&lt;p&gt;For payment detection, WooCommerce stores typically load Stripe.js or PayPal’s SDK directly on the checkout page. These are detected through HTML script tag analysis. Because WooCommerce is open-source, stores sometimes use less common payment gateways that are harder to detect—but the major processors (Stripe, PayPal, Square) all have well-known JavaScript fingerprints.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detection tip: If you want to confirm WooCommerce specifically (not just WordPress), check for WordPress detection signals first, then look for WooCommerce-specific indicators: the woocommerce body class, /wp-json/wc/ REST API routes, or wc- prefixed cookies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Custom-Built Ecommerce Stacks and How to Identify Them
&lt;/h2&gt;

&lt;p&gt;Not every online store runs on Shopify or WooCommerce. Large retailers, marketplaces, and niche platforms often build custom ecommerce systems or use platforms like Magento, BigCommerce, or Salesforce Commerce Cloud.&lt;/p&gt;

&lt;p&gt;Custom-built stores are identifiable by what is &lt;em&gt;absent&lt;/em&gt; from a scan: no Shopify DNS signatures, no WordPress/WooCommerce fingerprints, no known platform patterns. What you will find instead are the surrounding technologies: the CDN, the JavaScript framework powering the frontend (often React or Next.js—see our &lt;a href="https://detectzestack.com/blog/how-to-detect-nextjs-website" rel="noopener noreferrer"&gt;Next.js detection guide&lt;/a&gt;), the payment processor, and the analytics tools.&lt;/p&gt;

&lt;p&gt;BigCommerce stores are detectable via DNS: they CNAME to &lt;code&gt;*.mybigcommerce.com&lt;/code&gt;. Magento stores leave HTTP header fingerprints and distinctive HTML patterns. For platforms without strong fingerprints, the surrounding technologies often tell the story. A site running Next.js on Vercel with Stripe checkout and Algolia search is almost certainly a headless commerce implementation, even if the specific backend platform is opaque.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Primary Detection Signal&lt;/th&gt;
&lt;th&gt;Common Companion Technologies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Shopify&lt;/td&gt;
&lt;td&gt;CNAME: shops.myshopify.com&lt;/td&gt;
&lt;td&gt;Stripe, Cloudflare, Google Analytics, jQuery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WooCommerce&lt;/td&gt;
&lt;td&gt;/wp-content/, X-Powered-By: PHP&lt;/td&gt;
&lt;td&gt;WordPress, Stripe, PayPal, Cloudflare, jQuery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BigCommerce&lt;/td&gt;
&lt;td&gt;CNAME: *.mybigcommerce.com&lt;/td&gt;
&lt;td&gt;Cloudflare, Google Analytics, Stripe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Magento&lt;/td&gt;
&lt;td&gt;Mage cookies, /static/frontend/ paths&lt;/td&gt;
&lt;td&gt;PHP, MySQL, Varnish, Fastly, PayPal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom / Headless&lt;/td&gt;
&lt;td&gt;No known platform fingerprint&lt;/td&gt;
&lt;td&gt;React, Next.js, Vercel, Stripe, Algolia&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Analyze Any Ecommerce Tech Stack with the DetectZeStack API
&lt;/h2&gt;

&lt;p&gt;Manual inspection with &lt;code&gt;dig&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and browser dev tools works for one-off checks, but it does not scale. The DetectZeStack API combines DNS resolution, HTTP header analysis, HTML fingerprinting, and TLS certificate inspection into a single request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-Store Analysis with GET /analyze
&lt;/h3&gt;

&lt;p&gt;To analyze one store, use the free demo endpoint (no API key required, rate-limited to 20 requests per hour):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=allbirds.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.technologies[] | {name, categories, confidence}'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Shopify"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Ecommerce"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Cloudflare"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CDN"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 80
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Google Analytics"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Analytics"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Stripe"&lt;/span&gt;,
&lt;span class="s2"&gt;"categories"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Payment processors"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="s2"&gt;"confidence"&lt;/span&gt;: 100
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production use with higher rate limits, use the authenticated &lt;code&gt;GET /analyze&lt;/code&gt; endpoint via RapidAPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=allbirds.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.technologies'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes every detected technology with its name, categories, and confidence score. Confidence reflects the detection method: 100% for direct HTTP/HTML matches, 80% for DNS CNAME matches, 70% for TLS certificate matches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing Two Stores Side by Side with POST /compare
&lt;/h3&gt;

&lt;p&gt;To compare a Shopify store against a WooCommerce store, use the &lt;code&gt;POST /compare&lt;/code&gt; endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/compare"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["allbirds.com", "underarmour.com"]}'&lt;/span&gt; | jq &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The comparison response shows which technologies are shared between the two stores and which are unique to each. This is useful for competitive analysis: if a competitor uses a tool you do not, it may be worth investigating. If two stores in the same market use completely different stacks, that tells you there is no consensus on the “right” approach—an insight that matters for agencies advising clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Technologies to Watch in Ecommerce Stacks
&lt;/h2&gt;

&lt;p&gt;When analyzing ecommerce tech stacks, certain technologies carry more strategic weight than others. Here is what to pay attention to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Payment processor&lt;/strong&gt; — Stripe vs PayPal vs native platform payments. Stripe dominance in a market segment signals developer-oriented stores. PayPal presence often indicates a more traditional retail audience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN choice&lt;/strong&gt; — Cloudflare is the most common CDN across both Shopify and WooCommerce stores. CloudFront indicates AWS infrastructure. No CDN at all on a WooCommerce store is a red flag for performance. See our &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;CDN detection guide&lt;/a&gt; for the technical details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics tools&lt;/strong&gt; — Google Analytics is nearly universal, but the presence of additional tools like Hotjar (session recording), Mixpanel (product analytics), or Segment (data pipeline) indicates a more sophisticated operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript framework&lt;/strong&gt; — jQuery is still the default on most Shopify themes and WordPress sites. React or Vue.js in a store’s stack often means a headless architecture or a custom-built storefront. You can &lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;detect JavaScript frameworks&lt;/a&gt; through HTML fingerprints and JavaScript global variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security posture&lt;/strong&gt; — The TLS certificate issuer, the presence of security headers, and the server software version all provide signals. Shopify handles this automatically. WooCommerce stores vary widely, making security posture a useful differentiator.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scaling Ecommerce Tech Stack Analysis to Hundreds of Sites
&lt;/h2&gt;

&lt;p&gt;Analyzing one or two competitors is useful. Analyzing every store in a market segment is transformative. The &lt;code&gt;POST /analyze/batch&lt;/code&gt; endpoint accepts up to 10 URLs per request, letting you scan at scale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze/batch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"urls": ["store1.com", "store2.com", "store3.com"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a detailed walkthrough of scanning hundreds or thousands of domains—including a Python script with rate limiting and CSV output—see &lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At scale, patterns emerge that are invisible at the single-store level. You might discover that 70% of stores in a niche use Shopify, that Stripe is the payment processor for 85% of them, or that stores using Cloudflare CDN have measurably faster response times. This kind of data powers market research reports, competitive strategy, and sales targeting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Combine batch scanning with the GET /check endpoint to filter results. For example, after scanning 500 ecommerce domains, use /check?url=store.com&amp;amp;tech=Stripe to quickly verify which stores use Stripe without re-scanning the full tech stack.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ecommerce tech stack analysis goes beyond knowing whether a store uses Shopify or WooCommerce. The full picture—payment processors, CDNs, analytics tools, JavaScript frameworks, and security posture—reveals actionable intelligence for sales, competitive research, and migration planning.&lt;/p&gt;

&lt;p&gt;Shopify stores share a common infrastructure foundation but vary in their third-party integrations. WooCommerce stores vary at every layer, from hosting to CDN to payment gateway. Custom-built stores are identifiable by their surrounding technologies even when the platform itself leaves no fingerprint.&lt;/p&gt;

&lt;p&gt;The DetectZeStack API lets you automate this analysis across one store or thousands, returning structured data that you can filter, compare, and integrate into your workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/shopify-vs-woocommerce-detection" rel="noopener noreferrer"&gt;Shopify vs WooCommerce: How to Tell Which Platform a Site Uses&lt;/a&gt; — DNS fingerprints, HTML patterns, and cookie signatures for platform identification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Find Companies Using Stripe: Technographic Prospecting&lt;/a&gt; — Turn payment processor detection into qualified sales leads&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/batch-scan-1000-websites" rel="noopener noreferrer"&gt;How to Batch Scan 1,000 Websites for Tech Stack Data&lt;/a&gt; — Python script, curl examples, and optimization tips for scanning at scale&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/competitor-website-technology-analysis" rel="noopener noreferrer"&gt;Website Tech Lookup for Competitor Analysis&lt;/a&gt; — Full methodology for competitive technology intelligence&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;How to Detect CDN and Hosting Providers&lt;/a&gt; — DNS, headers, TLS, and IP range methods for infrastructure detection&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;Detect What JavaScript Framework a Website Uses&lt;/a&gt; — Identify React, Vue, Next.js, and other frontend technologies&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;Check If a Website Uses WordPress&lt;/a&gt; — Essential for WooCommerce detection since WooCommerce runs on WordPress&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-shopify" rel="noopener noreferrer"&gt;How to Detect if a Website Uses Shopify&lt;/a&gt; — Five detection methods for Shopify stores specifically&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Detect if a Website Uses React: 4 Proven Methods</title>
      <dc:creator>MikeL</dc:creator>
      <pubDate>Wed, 15 Apr 2026 22:11:22 +0000</pubDate>
      <link>https://dev.to/detectzestack/how-to-detect-if-a-website-uses-react-4-proven-methods-3f73</link>
      <guid>https://dev.to/detectzestack/how-to-detect-if-a-website-uses-react-4-proven-methods-3f73</guid>
      <description>&lt;p&gt;React powers a massive share of the modern web. From single-page apps to server-rendered sites built with Next.js, React’s footprint is everywhere—but not always obvious. A well-built React site can look indistinguishable from any other website in the browser. There’s no “Built with React” badge in the footer.&lt;/p&gt;

&lt;p&gt;Whether you’re evaluating a competitor’s technology choices, auditing a site for known React vulnerabilities, qualifying leads based on their tech stack, or simply curious about how a product is built, you need reliable detection methods. This guide covers four approaches, from quick manual checks to fully automated API-based detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Detect React on a Website
&lt;/h2&gt;

&lt;p&gt;Knowing whether a site runs React is more than trivia. Here are the practical reasons people look for this information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Competitive intelligence:&lt;/strong&gt; Understanding what frameworks your competitors chose—and whether they use plain React, Next.js, or Gatsby—reveals their engineering priorities. A Next.js site signals investment in SEO and performance. A client-side React SPA suggests a different set of trade-offs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security auditing:&lt;/strong&gt; React versions have known CVEs. Detecting an outdated React version on a target site is a concrete security finding. The same applies to Next.js, which has had its own set of vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sales prospecting:&lt;/strong&gt; If you sell developer tools, monitoring services, or React-specific products, knowing which companies use React determines whether your outreach is relevant. This is the same logic behind &lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;finding companies that use Stripe&lt;/a&gt; for payment-related prospecting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration planning:&lt;/strong&gt; Before migrating from Angular to React, or upgrading from React 17 to React 18, you need to know exactly what’s running in production—not what the internal documentation says.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hiring context:&lt;/strong&gt; Researching a company’s tech stack before an interview helps you understand what you’ll be working with and what questions to expect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 1 — Browser DevTools Console
&lt;/h2&gt;

&lt;p&gt;The fastest way to check if a website uses React is through the browser’s DevTools console. React leaves several fingerprints in the DOM and in JavaScript globals that you can query directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check for React Global Objects
&lt;/h3&gt;

&lt;p&gt;Open Chrome DevTools (press &lt;code&gt;F12&lt;/code&gt; or &lt;code&gt;Cmd+Option+I&lt;/code&gt; on macOS), switch to the Console tab, and run these checks:&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="c1"&gt;// Check for the React DevTools hook (present on most React sites)&lt;/span&gt;
&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__REACT_DEVTOOLS_GLOBAL_HOOK__&lt;/span&gt;

&lt;span class="c1"&gt;// Check for React Fiber on the root element&lt;/span&gt;
&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;_reactRootContainer&lt;/span&gt;

&lt;span class="c1"&gt;// Check for the data-reactroot attribute (React 15-16 pattern)&lt;/span&gt;
&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-reactroot]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Check for Next.js (built on React)&lt;/span&gt;
&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any of these return &lt;code&gt;true&lt;/code&gt;, the site is running React. The &lt;code&gt;__REACT_DEVTOOLS_GLOBAL_HOOK__&lt;/code&gt; check is the most reliable for modern React apps because React itself injects this hook during initialization, regardless of whether React DevTools is installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect the DOM for React Fiber Attributes
&lt;/h3&gt;

&lt;p&gt;React’s reconciler (Fiber) attaches internal properties to DOM nodes. In the Elements panel, select any element inside the React app and look at its properties in the Console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// Select an element, &lt;span class="k"&gt;then &lt;/span&gt;run:
&lt;span class="nv"&gt;$0&lt;/span&gt;.__reactFiber&lt;span class="nv"&gt;$ &lt;/span&gt;  // React 18+
&lt;span class="nv"&gt;$0&lt;/span&gt;.__reactInternalInstance&lt;span class="nv"&gt;$ &lt;/span&gt;  // React 16-17
&lt;span class="nv"&gt;$0&lt;/span&gt;._reactInternalFiber   // Older React versions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These properties are prefixed with a random hash (e.g., &lt;code&gt;__reactFiber$abc123&lt;/code&gt;), so you may need to type the prefix and let autocomplete show the full property name. If any of these properties exist on DOM nodes, React is managing that part of the page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Partial React usage: Some sites use React for only part of the page—a checkout widget, a search bar, or a dashboard embedded in a server-rendered page. In these cases, the React root may not be the top-level #root div. Check multiple elements if the top-level checks return false.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Method 2 — View Page Source Clues
&lt;/h2&gt;

&lt;p&gt;Viewing the HTML source (&lt;code&gt;Ctrl+U&lt;/code&gt; or &lt;code&gt;Cmd+Option+U&lt;/code&gt;) reveals patterns that indicate React, even before JavaScript executes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script Tags and Bundle Filenames
&lt;/h3&gt;

&lt;p&gt;React apps typically load bundled JavaScript files. Look for these patterns in the source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;react.production.min.js&lt;/code&gt; or &lt;code&gt;react-dom.production.min.js&lt;/code&gt; — Direct React library references, common on CDN-loaded setups.&lt;/li&gt;
&lt;li&gt;Webpack chunk filenames like &lt;code&gt;main.abc123.js&lt;/code&gt; or &lt;code&gt;static/js/bundle.js&lt;/code&gt; — While not React-specific, these are the default output of Create React App.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/__next/&lt;/code&gt; prefixed asset paths — A definitive Next.js marker. All static assets in Next.js are served from &lt;code&gt;/_next/static/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For client-side rendered React apps, the HTML source is often minimal—just a &lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; and script tags. This “empty shell” pattern is itself a strong signal of a client-side React SPA, though other frameworks like Vue and Angular can produce similar output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-Side Rendered React and Next.js Markers
&lt;/h3&gt;

&lt;p&gt;Server-rendered React sites (using Next.js, Remix, or custom SSR) include the full HTML content in the source. The distinguishing markers are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;div id="__next"&amp;gt;&lt;/code&gt; — The root element for Next.js applications.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;script id="__NEXT_DATA__" type="application/json"&amp;gt;&lt;/code&gt; — Contains the serialized page props, build ID, and routing data. This is the single most reliable indicator of Next.js.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-reactroot&lt;/code&gt; attribute on the root element — Added by &lt;code&gt;ReactDOMServer.renderToString()&lt;/code&gt; in React 15-16.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-nhead&lt;/code&gt; or &lt;code&gt;data-react-helmet&lt;/code&gt; attributes — Present when using helmet-style head management in React SSR.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Next.js fingerprint in page source --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"__next"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Full server-rendered HTML here --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"__NEXT_DATA__"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;props&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pageProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{}},&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buildId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Method 3 — Browser Extensions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React Developer Tools Extension
&lt;/h3&gt;

&lt;p&gt;The official React Developer Tools extension (available for Chrome and Firefox) is the most definitive manual check. When you visit a React-powered site, the extension icon lights up—blue for production builds, red for development builds. It also adds “Components” and “Profiler” tabs to DevTools, letting you inspect the React component tree directly.&lt;/p&gt;

&lt;p&gt;The extension works by detecting the &lt;code&gt;__REACT_DEVTOOLS_GLOBAL_HOOK__&lt;/code&gt; that React attaches during initialization. If React is present anywhere on the page—even in a small embedded widget—the extension will detect it.&lt;/p&gt;

&lt;p&gt;The limitation: you have to visit each site individually. This is fine for one-off checks but impractical if you need to scan hundreds of sites.&lt;/p&gt;

&lt;h3&gt;
  
  
  DetectZeStack Chrome Extension
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://chromewebstore.google.com/detail/detectzestack/mgecmlacndohfjfooobaebjkhekpjdod" rel="noopener noreferrer"&gt;DetectZeStack Chrome extension&lt;/a&gt; detects not just React but the entire technology stack—frameworks, CDNs, analytics tools, hosting providers, and more—all from a single toolbar click. Unlike React DevTools, which only identifies React, DetectZeStack shows the full picture: whether the site also uses Next.js, what &lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;CDN or hosting provider&lt;/a&gt; serves it, what analytics and marketing tools are loaded, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 4 — DetectZeStack API (Programmatic Detection)
&lt;/h2&gt;

&lt;p&gt;Manual methods work for spot checks. When you need to detect React across tens, hundreds, or thousands of sites—for lead qualification, competitive analysis, or security scanning—you need an API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-URL Analysis with curl
&lt;/h3&gt;

&lt;p&gt;The DetectZeStack API detects React and 7,300+ other technologies in a single request. Here is a quick check using the free demo endpoint (no API key required):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.com/demo?url=netflix.com"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.technologies[] | select(.name == "React" or .name == "Next.js")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production use with higher limits, use the RapidAPI endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=netflix.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="s1"&gt;'.technologies[] | select(.categories[] | contains("JavaScript frameworks"))'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reading the API Response
&lt;/h3&gt;

&lt;p&gt;The API returns a JSON object with all detected technologies. Here is what a React detection looks like in the response:&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;"url"&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://netflix.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"netflix.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scan_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"technologies"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"website"&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://reactjs.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"cpe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cpe:2.3:a:facebook:react:18.2:*:*:*:*:*:*:*"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Next.js"&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;"JavaScript frameworks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"confidence"&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;"website"&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://nextjs.org"&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;Key fields to look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; — The technology name. React and Next.js are reported separately, so you can distinguish between the two.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confidence&lt;/code&gt; — How certain the detection is (0-100). A confidence of 100 means the fingerprint matched unambiguously.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt; — When detectable, the specific React version. Useful for security auditing—you can cross-reference this against known CVEs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cpe&lt;/code&gt; — The &lt;a href="https://detectzestack.com/blog/cpe-identifiers-explained-for-security-teams" rel="noopener noreferrer"&gt;CPE identifier&lt;/a&gt; for the technology, letting you look up vulnerabilities in the NVD directly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;categories&lt;/code&gt; — React appears under “JavaScript frameworks.” This lets you filter the response to only show front-end frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Batch Detection Across Multiple Sites
&lt;/h3&gt;

&lt;p&gt;To scan a list of domains for React usage, loop through them with curl or use a script. Here is a quick bash one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in &lt;/span&gt;netflix.com airbnb.com stripe.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;: "&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://detectzestack.p.rapidapi.com/analyze?url=&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Key: YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-RapidAPI-Host: detectzestack.p.rapidapi.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'[.technologies[] | select(.name == "React" or .name == "Next.js") | .name] | if length == 0 then "not detected" else join(", ") end'&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For larger-scale scanning, see the &lt;a href="https://detectzestack.com/blog/website-technology-detection-python-tutorial" rel="noopener noreferrer"&gt;Python tutorial&lt;/a&gt; which covers batch scanning with rate limiting and CSV export.&lt;/p&gt;

&lt;h2&gt;
  
  
  React vs Next.js — What the Detection Tells You
&lt;/h2&gt;

&lt;p&gt;Every Next.js site uses React, but not every React site uses Next.js. Understanding the distinction matters for competitive analysis and technical assessment:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Plain React (CRA/Vite)&lt;/th&gt;
&lt;th&gt;Next.js&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Root element&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page data&lt;/td&gt;
&lt;td&gt;None in source&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;NEXT_DATA&lt;/strong&gt; script tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asset paths&lt;/td&gt;
&lt;td&gt;/static/js/main.*.js&lt;/td&gt;
&lt;td&gt;/_next/static/chunks/*.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP headers&lt;/td&gt;
&lt;td&gt;None specific&lt;/td&gt;
&lt;td&gt;X-Nextjs-Cache (on ISR pages)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;Possible but manual&lt;/td&gt;
&lt;td&gt;Built-in (SSR/SSG/ISR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering pattern&lt;/td&gt;
&lt;td&gt;Client-side (empty shell)&lt;/td&gt;
&lt;td&gt;Server-rendered HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When the DetectZeStack API reports both “React” and “Next.js,” it means the site uses Next.js as the framework layer on top of React. If only “React” is reported, the site uses React directly—possibly with Create React App, Vite, Gatsby, Remix, or a custom setup.&lt;/p&gt;

&lt;p&gt;Other React-based frameworks you may see detected alongside React include Gatsby (which uses React for its component model and adds a static site generation layer) and Remix (which, like Next.js, adds server-side rendering to React). For a broader overview of detecting all JavaScript frameworks, see &lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;How to Detect What JavaScript Framework a Website Uses&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why this matters for sales: A company running Next.js has likely invested in performance and SEO—they may be interested in monitoring and analytics tools. A company running a client-side React SPA may be more interested in performance optimization and bundle analysis tools. The framework choice signals the team’s priorities. For more on using tech detection for outreach, see Tech Stack Enrichment for Sales Teams.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Get Started with Programmatic React Detection
&lt;/h2&gt;

&lt;p&gt;Manual checks are fine for occasional curiosity. For anything systematic—lead qualification, competitive research, security scanning, or portfolio analysis—an API is the only practical approach.&lt;/p&gt;

&lt;p&gt;The DetectZeStack API gives you React detection plus 7,300+ other technology fingerprints in a single call. Every request also includes DNS-based infrastructure detection, TLS certificate analysis, and CPE identifiers for vulnerability lookups—layers that no browser-based method can match.&lt;/p&gt;

&lt;p&gt;The free tier includes 100 requests per month with no credit card required. That is enough to scan your competitor list, audit a client portfolio, or build a proof-of-concept integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-javascript-framework-website" rel="noopener noreferrer"&gt;Detect What JavaScript Framework a Website Uses&lt;/a&gt; — React, Vue, Angular, Next.js, and Svelte detection compared&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-any-website-tech-stack-with-single-api-call" rel="noopener noreferrer"&gt;Detect Any Website's Tech Stack with a Single API Call&lt;/a&gt; — Overview of all four detection layers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/website-technology-checker-api" rel="noopener noreferrer"&gt;Website Technology Checker API&lt;/a&gt; — Full endpoint reference and integration guide&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/cpe-identifiers-explained-for-security-teams" rel="noopener noreferrer"&gt;CPE Identifiers Explained for Security Teams&lt;/a&gt; — Cross-reference detected React versions with known CVEs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/find-companies-using-stripe-technographic-prospecting" rel="noopener noreferrer"&gt;Find Companies Using Stripe&lt;/a&gt; — Technographic prospecting with the same API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/website-technology-detection-python-tutorial" rel="noopener noreferrer"&gt;Website Technology Detection: Python Tutorial&lt;/a&gt; — Batch scanning with Python and CSV export&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/check-if-website-uses-wordpress" rel="noopener noreferrer"&gt;Check If a Website Uses WordPress&lt;/a&gt; — CMS detection guide&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/detect-cdn-hosting-provider" rel="noopener noreferrer"&gt;How to Detect CDN and Hosting Provider&lt;/a&gt; — Infrastructure-layer detection&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-nextjs-website" rel="noopener noreferrer"&gt;How to Detect if a Website Uses Next.js&lt;/a&gt; — Next.js-specific detection with Pages Router vs App Router fingerprints&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-vue-website" rel="noopener noreferrer"&gt;How to Detect if a Website Uses Vue.js&lt;/a&gt; — Vue and Nuxt detection from console checks to API automation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://detectzestack.com/blog/how-to-detect-tailwind-css" rel="noopener noreferrer"&gt;How to Detect Tailwind CSS on Any Website&lt;/a&gt; — 5 methods to identify Tailwind from DOM inspection to API automation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>techstack</category>
      <category>webdev</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
