<?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: Henley Wing</title>
    <description>The latest articles on DEV Community by Henley Wing (@henley_wing_9424eb9a3177c).</description>
    <link>https://dev.to/henley_wing_9424eb9a3177c</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3730786%2F93b095fa-acda-4ab5-9d25-2182c154d0bf.webp</url>
      <title>DEV Community: Henley Wing</title>
      <link>https://dev.to/henley_wing_9424eb9a3177c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/henley_wing_9424eb9a3177c"/>
    <language>en</language>
    <item>
      <title>Jira vs Linear: Who's winning new customers?</title>
      <dc:creator>Henley Wing</dc:creator>
      <pubDate>Thu, 07 May 2026 17:09:26 +0000</pubDate>
      <link>https://dev.to/henley_wing_9424eb9a3177c/jira-vs-linear-whos-winning-new-customers-5ahe</link>
      <guid>https://dev.to/henley_wing_9424eb9a3177c/jira-vs-linear-whos-winning-new-customers-5ahe</guid>
      <description>&lt;p&gt;If you spend any time on tech Twitter or developer Reddit, you already know the script. Someone complains about Jira. Someone tells them to switch to Linear. A third person jumps in to defend Jira if you just configure it properly. Repeat weekly.&lt;/p&gt;

&lt;p&gt;Plenty of opinions, very little data. So I went looking for the actual numbers, using &lt;a href="https://bloomberry.com/data/atlassian-jira/" rel="noopener noreferrer"&gt;adoption-signal data from Bloomberry&lt;/a&gt;, which tracks new customers through clickstream data - meaning when a new company-specific URL shows up (a new Atlassian Jira workspace URL, a new Linear team URL, and so on), it's logged as a new customer for that tool. &lt;/p&gt;

&lt;p&gt;The dataset covers roughly a million company domains tracked between February 2025 and April 2026.&lt;/p&gt;

&lt;p&gt;A quick definition before we get into it: when I say "customer," I mean any company that newly adopted the tool, whether on a free trial, free tier, or paid plan. &lt;/p&gt;

&lt;p&gt;Here's what the numbers say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linear is catching Jira fast
&lt;/h2&gt;

&lt;p&gt;Twelve months ago, this race was not close. Between February and April 2025, Jira picked up 2,225 new companies. Linear picked up 807. Jira was acquiring almost three times as many new customers each month, every month.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7cgs5dz390sa3i729wr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7cgs5dz390sa3i729wr.png" alt="Jira vs Linear new customer growth" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A year later, the gap has nearly disappeared. In February through April 2026, Linear added 1,351 new companies. Jira added 1,524. The two are now within 12% of each other, and the lines are heading in opposite directions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Feb–Apr 2025&lt;/th&gt;
&lt;th&gt;Feb–Apr 2026&lt;/th&gt;
&lt;th&gt;YoY change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;td&gt;807&lt;/td&gt;
&lt;td&gt;1,351&lt;/td&gt;
&lt;td&gt;+67%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jira&lt;/td&gt;
&lt;td&gt;2,225&lt;/td&gt;
&lt;td&gt;1,524&lt;/td&gt;
&lt;td&gt;-32%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Linear added two-thirds more new customers in the most recent three-month window than the same window a year ago. Jira added roughly a third fewer. If both trends hold, Linear overtakes Jira on new customer acquisition within a quarter or two.&lt;/p&gt;

&lt;p&gt;There is one important wrinkle on the Atlassian side. New Jira signups are dropping, but the number of existing Atlassian customers expanding the product across their organizations has held steady. The way to detect organizational expansion in clickstream data is by looking for SSO setup with Atlassian - when a company configures SSO, it usually means the tool is being deployed beyond a single team. That signal stayed roughly flat year-over-year, up about 4%, while new Jira customer signups dropped 32%.&lt;/p&gt;

&lt;p&gt;This isn't the same as revenue expansion or net revenue retention - we're not measuring seat counts or contract value. But it is a useful leading indicator of organizational rollout. And the two trend lines, when you look at them together, are pointing in opposite directions: existing customers keep expanding their footprint while new customers are signing up at a slower rate.&lt;/p&gt;

&lt;p&gt;That's consistent with what Atlassian's CFO has been telling Wall Street for a while now. Revenue growth is being driven by existing customers expanding seats, not by net-new logos. The Atlassian story isn't "the product is dying." It's "the funnel for new customers is slowing, and we're making it up by selling more to the people we already have."&lt;/p&gt;

&lt;h2&gt;
  
  
  Different customers, different sizes
&lt;/h2&gt;

&lt;p&gt;The two products serve very different parts of the market, which becomes obvious as soon as you cut the data by company size. I joined the customer data with LinkedIn organization data to see how each customer base breaks down by headcount:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company size&lt;/th&gt;
&lt;th&gt;Linear %&lt;/th&gt;
&lt;th&gt;Jira %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2–10&lt;/td&gt;
&lt;td&gt;12.3%&lt;/td&gt;
&lt;td&gt;9.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11–50&lt;/td&gt;
&lt;td&gt;45.6%&lt;/td&gt;
&lt;td&gt;38.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;51–200&lt;/td&gt;
&lt;td&gt;27.0%&lt;/td&gt;
&lt;td&gt;28.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201–500&lt;/td&gt;
&lt;td&gt;7.9%&lt;/td&gt;
&lt;td&gt;11.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;501–1,000&lt;/td&gt;
&lt;td&gt;3.0%&lt;/td&gt;
&lt;td&gt;5.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,001–5,000&lt;/td&gt;
&lt;td&gt;2.8%&lt;/td&gt;
&lt;td&gt;5.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5,001–10,000&lt;/td&gt;
&lt;td&gt;0.6%&lt;/td&gt;
&lt;td&gt;1.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,001+&lt;/td&gt;
&lt;td&gt;0.9%&lt;/td&gt;
&lt;td&gt;1.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Linear is concentrated in one specific band: companies with 11 to 200 employees. Almost three-quarters of Linear customers - 72.6% - sit in that range, and the 11-to-50 bucket alone accounts for 46% of the entire customer base. That single bucket is bigger than any equivalent bucket for Jira.&lt;/p&gt;

&lt;p&gt;Jira's distribution is wider on every dimension. It has slightly fewer customers in the smallest segments, but consistently more share from 200 employees up. The clearest gap shows up in the 1,001-to-5,000 bucket, where Jira has 5.1% of customers and Linear has 2.8%. Jira's enterprise tail is roughly twice as long.&lt;/p&gt;

&lt;p&gt;The short version: a 25-person engineering team is probably picking Linear. A 2,000-person engineering org is probably staying on Jira. The interesting fight is in the 200-to-500 zone, where the choice really does come down to the team's preferences, the existing tooling stack, and how much process the company has built up around the issue tracker.&lt;/p&gt;

&lt;h2&gt;
  
  
  The industry split
&lt;/h2&gt;

&lt;p&gt;The size split tells one story; the industry split tells a related but distinct one. For each tool, I calculated the &lt;em&gt;lift&lt;/em&gt; over baseline: how much more likely a company in a given sector is to use the tool than the average company across the dataset. A lift of 4x means a company in that sector is four times more likely to use the tool than the typical company.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sector&lt;/th&gt;
&lt;th&gt;Linear lift&lt;/th&gt;
&lt;th&gt;Jira lift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Software development&lt;/td&gt;
&lt;td&gt;4.6x&lt;/td&gt;
&lt;td&gt;2.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technology, information, internet&lt;/td&gt;
&lt;td&gt;2.8x&lt;/td&gt;
&lt;td&gt;1.3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Computer and network security&lt;/td&gt;
&lt;td&gt;2.6x&lt;/td&gt;
&lt;td&gt;2.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Computer games&lt;/td&gt;
&lt;td&gt;2.2x&lt;/td&gt;
&lt;td&gt;2.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-learning providers&lt;/td&gt;
&lt;td&gt;2.0x&lt;/td&gt;
&lt;td&gt;1.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IT services and consulting&lt;/td&gt;
&lt;td&gt;1.5x&lt;/td&gt;
&lt;td&gt;1.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medical equipment manufacturing&lt;/td&gt;
&lt;td&gt;below baseline&lt;/td&gt;
&lt;td&gt;1.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Biotechnology research&lt;/td&gt;
&lt;td&gt;below baseline&lt;/td&gt;
&lt;td&gt;1.3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telecommunications&lt;/td&gt;
&lt;td&gt;below baseline&lt;/td&gt;
&lt;td&gt;1.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insurance&lt;/td&gt;
&lt;td&gt;below baseline&lt;/td&gt;
&lt;td&gt;1.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Financial services&lt;/td&gt;
&lt;td&gt;1.4x&lt;/td&gt;
&lt;td&gt;1.3x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both tools peak in software, but with very different intensities. Linear's lift in software development is 4.6x - much sharper than Jira's 2.8x. Linear's customer base is more concentrated in tech as a percentage. But because Jira is the bigger product overall, it actually has more software customers in absolute terms.&lt;/p&gt;

&lt;p&gt;The more revealing rows are the ones near the bottom of the table. Medical equipment, biotech, telecom, insurance - these are sectors where Jira has real penetration and Linear is below baseline. The common thread across all of them is heavy compliance and audit requirements: regulated workflows, change-management documentation, audit trails, role-based permissions, the kind of features that take years to build properly. Atlassian has been building for that buyer for two decades. Linear, based on its public roadmap, has not been and isn't planning to.&lt;/p&gt;

&lt;p&gt;You can describe each product's identity in one line. Linear is the issue tracker for software companies and adjacent tech. Jira is the issue tracker for software companies, adjacent tech, and every regulated industry that ships software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Funding stage tells the same story from a different angle
&lt;/h2&gt;

&lt;p&gt;The size and industry data line up neatly with funding stage. Among customers where I have funding-stage data, here's how each tool's customer base breaks down:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Funding stage&lt;/th&gt;
&lt;th&gt;Linear %&lt;/th&gt;
&lt;th&gt;Jira %&lt;/th&gt;
&lt;th&gt;Linear / Jira&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Early stage (seed, pre-seed, angel)&lt;/td&gt;
&lt;td&gt;37.5%&lt;/td&gt;
&lt;td&gt;27.7%&lt;/td&gt;
&lt;td&gt;1.35x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Series A / B / C&lt;/td&gt;
&lt;td&gt;25.6%&lt;/td&gt;
&lt;td&gt;19.2%&lt;/td&gt;
&lt;td&gt;1.33x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Series D+&lt;/td&gt;
&lt;td&gt;2.5%&lt;/td&gt;
&lt;td&gt;2.1%&lt;/td&gt;
&lt;td&gt;1.19x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Post-IPO&lt;/td&gt;
&lt;td&gt;2.4%&lt;/td&gt;
&lt;td&gt;5.4%&lt;/td&gt;
&lt;td&gt;0.44x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Private equity&lt;/td&gt;
&lt;td&gt;4.1%&lt;/td&gt;
&lt;td&gt;8.0%&lt;/td&gt;
&lt;td&gt;0.51x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debt / grant / non-equity&lt;/td&gt;
&lt;td&gt;8.6%&lt;/td&gt;
&lt;td&gt;14.2%&lt;/td&gt;
&lt;td&gt;0.61x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Linear is the venture-backed-startup product. Two-thirds of Linear customers with funding data are at Series C or earlier. The early-stage cohort alone - seed, pre-seed, and angel-funded companies - makes up 37.5% of the customer base. This is exactly who Linear was built for, and it's exactly who is signing up.&lt;/p&gt;

&lt;p&gt;Jira is the established-business product. Post-IPO companies are 2.3 times more concentrated in Jira's customer base than Linear's. PE-backed companies are 2x more concentrated. Even debt and grant-funded organizations - universities, nonprofits, public-sector adjacent groups - skew toward Jira by 1.6x.&lt;/p&gt;

&lt;p&gt;This is the size cut and the industry cut viewed from a third angle, and they all paint the same picture. Linear's customer is a small, fast-growing, venture-backed company. Jira's customer is everyone else who needs an issue tracker - including a meaningful share of small companies, but also the big established ones that Linear hasn't reached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tell me your stack and I'll guess your tracker
&lt;/h2&gt;

&lt;p&gt;This was the single most interesting cut in the analysis. If I tell you a company uses Linear, what's the rest of their stack likely to look like? And how does that compare to Jira?&lt;/p&gt;

&lt;p&gt;To answer that, I calculated lift again, but this time within each tool's customer base: how much more likely a Linear (or Jira) customer is to also use a given tool, compared to the baseline rate across all companies in the dataset.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Linear lift&lt;/th&gt;
&lt;th&gt;Jira lift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intercom (customer messaging)&lt;/td&gt;
&lt;td&gt;122x&lt;/td&gt;
&lt;td&gt;50x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentry (error monitoring)&lt;/td&gt;
&lt;td&gt;109x&lt;/td&gt;
&lt;td&gt;51x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amplitude (product analytics)&lt;/td&gt;
&lt;td&gt;109x&lt;/td&gt;
&lt;td&gt;45x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chargebee (subscription billing)&lt;/td&gt;
&lt;td&gt;103x&lt;/td&gt;
&lt;td&gt;48x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Workers (edge compute)&lt;/td&gt;
&lt;td&gt;94x&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retool (internal tools)&lt;/td&gt;
&lt;td&gt;90x&lt;/td&gt;
&lt;td&gt;41x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vercel Pro (front-end deploy)&lt;/td&gt;
&lt;td&gt;88x&lt;/td&gt;
&lt;td&gt;32x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PagerDuty (incident response)&lt;/td&gt;
&lt;td&gt;88x&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weights and Biases (ML experiments)&lt;/td&gt;
&lt;td&gt;78x&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor (AI code editor)&lt;/td&gt;
&lt;td&gt;73x&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft 365&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;td&gt;3.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure DevOps&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;td&gt;19x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Salesforce CRM&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;td&gt;21x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Salesforce Experience Cloud&lt;/td&gt;
&lt;td&gt;not in top 30&lt;/td&gt;
&lt;td&gt;37x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Linear customers live in the modern startup stack. Sentry, Amplitude, Chargebee, Vercel, Retool, PagerDuty, Intercom - these are the names you'd expect to see on a Y Combinator company's tools list. The lift values are striking. Intercom shows up at 122x baseline, Sentry at 109x, Chargebee at 103x. The same patterns are present in Jira's customer base, but at two to three times lower lift.&lt;/p&gt;

&lt;p&gt;The AI-tooling signal is even sharper. Cursor at 73x, Weights and Biases at 78x, Claude at 37x. These are tools that have only been in widespread use for about 18 months, and Linear customers are picking them up at extraordinary rates relative to the rest of the market. Linear customers aren't just modern - they're early on the AI-coding curve.&lt;/p&gt;

&lt;p&gt;Jira customers live in a different world. The same modern dev tools appear in Jira's top co-vendors too, but at notably lower lift. Jira's distinctive companions are the big enterprise platforms: Microsoft 365, Azure DevOps, Salesforce CRM, Salesforce Experience Cloud. None of those crack Linear's top 30.&lt;/p&gt;

&lt;p&gt;The takeaway is simple. Show me what tools a company uses, and I can guess which issue tracker they picked. A company on Vercel + Cursor + Sentry + Amplitude is overwhelmingly going to be on Linear. A company on Microsoft 365 + Azure DevOps + Salesforce is overwhelmingly going to be on Jira. The two stacks barely overlap, even though both products in theory solve the same problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  How they sell mirrors who they sell to
&lt;/h2&gt;

&lt;p&gt;There's another dimension worth pulling apart: how the customers of each tool actually go to market themselves. Two simple proxies are useful here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;public pricing page&lt;/strong&gt; on a company's website is a signal of self-serve, product-led-growth motion. The company is saying you can decide whether to buy without talking to anyone first.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;"Get a Demo" or "Request Demo" CTA&lt;/strong&gt; on the homepage is a signal of sales-led motion. The buyer can't price-shop or sign up; they have to talk to a salesperson before anything happens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These signals are noisy. Some PLG companies don't publish pricing - Linear itself buries it pretty deep, ironically - and some enterprise companies do. The honest framing isn't "every Linear customer is PLG." It's: among the companies where we can detect a clear go-to-market signal, what's the ratio?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Customer base&lt;/th&gt;
&lt;th&gt;Pricing page (PLG)&lt;/th&gt;
&lt;th&gt;Demo CTA (sales-led)&lt;/th&gt;
&lt;th&gt;Demo : Pricing ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;td&gt;2,589 (39%)&lt;/td&gt;
&lt;td&gt;3,981 (61%)&lt;/td&gt;
&lt;td&gt;1.54x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jira&lt;/td&gt;
&lt;td&gt;2,634 (30%)&lt;/td&gt;
&lt;td&gt;6,106 (70%)&lt;/td&gt;
&lt;td&gt;2.32x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Linear's customer base is meaningfully more PLG-leaning. 39% of Linear customers with a detected GTM signal have a public pricing page, versus 30% for Jira. Phrased the other way around, Jira's customer base is about 50% more sales-led than Linear's - a 2.32x demo-to-pricing ratio, against Linear's 1.54x.&lt;/p&gt;

&lt;p&gt;This tracks with everything else. Linear's customers are smaller and earlier stage, often selling to other developers and product managers who want to evaluate quickly without having to sit through a discovery call. Jira's customers are larger and more enterprise, often selling complex products on bigger contracts where buyers expect a sales motion. The same forces that produced "Linear customers use Stripe and Vercel; Jira customers use Salesforce and Microsoft 365" also produced "Linear customers ship pricing pages; Jira customers ship demo CTAs." It's the same underlying fact viewed through a different lens.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then there's Monday
&lt;/h2&gt;

&lt;p&gt;The Linear vs. Jira fight is the loud one in the project management space, but it's not the only race in the market. So I ran the same time-series analysis on Monday, which spends a fortune on TV and YouTube ads telling teams their tool will fix everything. The result was striking.&lt;/p&gt;

&lt;p&gt;Monday's new customer acquisition has been in steady decline for the entire 14 months I tracked. Comparing March-April 2025 to March-April 2026, Monday went from 396 new companies to 235. That's a 41% drop year-over-year - sharper than Jira's 32% decline over the same window. December 2025 was Monday's worst month in the entire dataset, at just 83 new companies.&lt;/p&gt;

&lt;p&gt;This isn't only what the third-party data shows. It's also what Monday's own management is telling investors. On the Q4 2025 earnings call, co-CEO Roy Mann described Monday's self-serve channels as "choppy," with persistently higher customer acquisition costs and lower returns in the SMB segment. The company told Wall Street not to expect any improvement in no-touch performance marketing through 2026. They withdrew their previously communicated 2027 targets. The stock dropped 13% on the report.&lt;/p&gt;

&lt;p&gt;So when the data shows Monday's new business customer acquisition declining 41% year-over-year, with December 2025 marking their lowest month in the dataset, it's not a noisy signal. The company's own CEO is saying out loud, on an earnings call, that the SMB self-serve funnel is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it all mean
&lt;/h2&gt;

&lt;p&gt;For Linear, the momentum is real and broad-based. They own the modern, AI-era startup cohort, which happens to be the fastest-growing one. The harder question is what comes next. To keep growing at this pace, Linear needs to crack regulated industries or move up-market into 500-plus-employee organizations where Jira is entrenched. Both are hard. The regulated-industry play takes years of compliance work that doesn't show up in feature velocity. The up-market play means selling to procurement and IT departments that have been on Jira for a decade and have built every internal process around it.&lt;/p&gt;

&lt;p&gt;For Atlassian, the regulated-industry moat is real and durable. Medical device companies do not switch issue trackers because of a viral Twitter thread. But losing the early-stage tech-startup funnel is a real long-term problem. Today's Series A is tomorrow's Series D, and those companies will carry Linear with them as they scale. The size-and-funding data isn't just a snapshot; it's a leading indicator of who the next decade's enterprise customers will be using.&lt;/p&gt;

&lt;p&gt;For Monday, the decline is the most striking finding in the analysis. With their marketing budget and brand recognition, they had every opportunity to be the company that beat Linear in the SMB segment. Instead, their net-new customer growth is falling faster than any tool I tracked, and management is saying the funnel itself is broken. That's a different kind of problem from a tool that's losing a feature war. It suggests something has changed in how SMBs discover and choose project management software, and Monday's strategy was built for the old way.&lt;/p&gt;

&lt;p&gt;The tools we pick early in a company's life tend to come with us as we grow. That's what makes the current moment interesting. The next decade of issue tracking is being decided right now, in the choices being made by 30-person startups.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Methodology: data comes from Bloomberry's technographic intelligence product, which detects new customers via clickstream signals - when a new Atlassian Jira workspace URL, Linear team URL, or equivalent product-specific URL appears, it's logged as a new customer for that tool. The same set of one million randomly sampled company domains was tracked for all products across 15 months (February 2025 to April 2026), so the comparisons are apples-to-apples. The "new Jira customer" count specifically captures companies that signed up for Jira as a project management tool - it does not include companies that originally signed up for Confluence or Jira Service Management and later expanded into Jira. Atlassian's true new-user flow is therefore larger than what's shown, but the methodology is identical across all 15 months, so the directional trends are valid.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>data</category>
      <category>productivity</category>
      <category>saas</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Detecting paying Cloudflare customers (for fun and profit)</title>
      <dc:creator>Henley Wing</dc:creator>
      <pubDate>Sun, 03 May 2026 14:48:57 +0000</pubDate>
      <link>https://dev.to/henley_wing_9424eb9a3177c/detecting-paying-cloudflare-customers-for-fun-and-profit-2dko</link>
      <guid>https://dev.to/henley_wing_9424eb9a3177c/detecting-paying-cloudflare-customers-for-fun-and-profit-2dko</guid>
      <description>&lt;p&gt;A while back I got curious about whether you could tell the difference between a company paying &lt;a href="https://bloomberry.com/data/cloudflare/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt; serious money versus one that signed up for the free plan and forgot about it.&lt;/p&gt;

&lt;p&gt;First thing I tried: response headers. Don’t bother. Cloudflare returns identical header names whether you’re running on Workers, sitting on an Enterprise contract, or using the free tier. That’s intentional – Cloudflare doesn’t want their product tier to leak through HTTP.&lt;/p&gt;

&lt;p&gt;What isn’t intentional is everything else. Here’s a full walkthrough, ordered from weakest to strongest signal. Code samples are Python, but everything here is just DNS lookups and HTTP requests – translate to whatever language you want.&lt;/p&gt;




&lt;h2&gt;
  
  
  Baseline: Are They Even Using Cloudflare?
&lt;/h2&gt;

&lt;p&gt;Before anything else you need to confirm you’re actually looking at a Cloudflare-proxied domain.&lt;/p&gt;

&lt;p&gt;Cloudflare publishes their IP ranges publicly at &lt;a href="https://www.cloudflare.com/ips/" rel="noopener noreferrer"&gt;cloudflare.com/ips&lt;/a&gt;. Resolve the domain’s A record, check if it falls inside those ranges. Or check the nameservers – Cloudflare customers using the full proxy will have &lt;code&gt;ns1.cloudflare.com&lt;/code&gt; / &lt;code&gt;ns2.cloudflare.com&lt;/code&gt; as their NS records.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_cloudflare&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="n"&gt;a_records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_a&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="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cloudflare_ip_ranges&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a_records&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;True&lt;/span&gt;

    &lt;span class="n"&gt;ns_records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_ns&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloudflare&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;ns&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ns_records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://radar.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare Radar&lt;/a&gt; publishes the top million domains by traffic. DNS-resolve all of them against the Cloudflare IP list and you’ve got a large working dataset in under an hour.&lt;/p&gt;

&lt;p&gt;The catch: this puts you at roughly 20% of the web. That’s a lot of personal blogs and parked domains. The signals below are about separating the serious customers from the noise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #1: Dashboard SSO TXT Record
&lt;/h2&gt;

&lt;p&gt;Straightforward to check, surprisingly revealing.&lt;/p&gt;

&lt;p&gt;When a company configures SSO for their Cloudflare dashboard login (wiring it into Okta, Azure AD, or another SAML identity provider), the setup process adds a TXT record to their DNS zone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;cloudflare_dashboard_sso&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1111111&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_dashboard_sso&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="n"&gt;txt_records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_txt&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloudflare_dashboard_sso=&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;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;txt_records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This used to be locked to Enterprise. Cloudflare has since relaxed that, so it’s not a guaranteed paid signal anymore. But practically speaking: nobody running a hobby project or a small business on the free tier is going to spend their afternoon setting up a SAML connector. The configuration effort alone filters out the noise. Treat it as a soft signal of intentional, serious usage.&lt;/p&gt;

&lt;p&gt;Fast to run across the full Radar million since it’s just a DNS query.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #2: Cloudflare Email Products (MX Records)
&lt;/h2&gt;

&lt;p&gt;Two completely different Cloudflare email products, both detectable via MX record inspection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://developers.cloudflare.com/email-routing/" rel="noopener noreferrer"&gt;Email Routing&lt;/a&gt;&lt;/strong&gt; is a free forwarding service. When enabled, Cloudflare replaces the domain’s MX records with their own mail servers. The pattern looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MX 52  route1.mx.cloudflare.net
MX 98  route2.mx.cloudflare.net
MX 91  route3.mx.cloudflare.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some zones use named variants instead: &lt;code&gt;amir.mx.cloudflare.net&lt;/code&gt;, &lt;code&gt;linda.mx.cloudflare.net&lt;/code&gt;, &lt;code&gt;isaac.mx.cloudflare.net&lt;/code&gt;. Either way, the &lt;code&gt;*.mx.cloudflare.net&lt;/code&gt; suffix is the tell. Since this is a free product it’s a weak signal on its own – but it does confirm the domain is actively managed in Cloudflare rather than just having DNS parked there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.cloudflare.com/zero-trust/email-security/" rel="noopener noreferrer"&gt;Email Security&lt;/a&gt;&lt;/strong&gt; (formerly Area 1) is the paid product. It’s an anti-phishing and email threat detection platform aimed squarely at enterprise security teams. When deployed in inline mode, it sits in front of the customer’s mail provider as the primary MX record, inspecting every inbound message before it reaches Google Workspace or Microsoft 365. The MX records point to Area 1’s inbound gateways rather than the customer’s mail provider directly – look for &lt;code&gt;*.area1security.com&lt;/code&gt; or Cloudflare-owned inbound gateway hostnames.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;email_signals&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="n"&gt;mx_records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_mx&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="n"&gt;mx_hosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&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;mx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mx_records&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email_routing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mx.cloudflare.net&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;mx&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mx_hosts&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email_security&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;area1security.com&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;mx&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mx_hosts&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;Email Security is Enterprise territory – it’s a dedicated security product with per-seat pricing and a sales process. Seeing those MX records on a domain is a strong indicator of an Enterprise relationship.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #3: Bot Defense Cookies
&lt;/h2&gt;

&lt;p&gt;Passive signal – no probing needed, just inspect cookies on a normal response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;__cf_bm&lt;/code&gt;&lt;/strong&gt; shows up when any of Cloudflare’s bot defense products are active: &lt;a href="https://www.cloudflare.com/application-services/products/bot-management/" rel="noopener noreferrer"&gt;Bot Management&lt;/a&gt; (Enterprise-only), &lt;a href="https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/" rel="noopener noreferrer"&gt;Super Bot Fight Mode&lt;/a&gt; (Pro+), or &lt;a href="https://developers.cloudflare.com/bots/get-started/free/" rel="noopener noreferrer"&gt;Bot Fight Mode&lt;/a&gt; (free). The cookie itself doesn’t tell you which tier, but its presence means someone has actively configured bot protection beyond the defaults.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;_cfuvid&lt;/code&gt;&lt;/strong&gt; appears when a site is using &lt;code&gt;cf.unique_visitor_id&lt;/code&gt; inside a WAF Rate Limiting Rule to track unique visitors behind shared IPs (corporate NATs, etc.). Available on any plan, but writing custom rate limiting rules signals intentional configuration rather than a default install.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cookie_signals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&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;set-cookie&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bot_management&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;__cf_bm=&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;cookies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate_limiting&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;_cfuvid=&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;cookies&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;Neither cookie alone proves paid status. Together with other signals they help build the picture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #4: Custom Error Pages
&lt;/h2&gt;

&lt;p&gt;A bit more involved, but one of the more reliable signals for Pro+ customers.&lt;/p&gt;

&lt;p&gt;Cloudflare’s default error pages have consistent fingerprints you can match against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"Attention Required! | Cloudflare"&lt;/code&gt; – WAF block page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_cf_chl_opt&lt;/code&gt; – challenge/CAPTCHA page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cf-error-details&lt;/code&gt; – diagnostic error pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro plan and above lets customers replace these with &lt;a href="https://developers.cloudflare.com/rules/custom-error-responses/" rel="noopener noreferrer"&gt;custom error responses&lt;/a&gt;. Plenty of paying customers do this because Cloudflare’s default error page clashes with their brand.&lt;/p&gt;

&lt;p&gt;The detection relies on a quirk: Cloudflare’s edge always writes the &lt;code&gt;cf-ray&lt;/code&gt; header into every response. This Ray ID is generated at the edge – the customer’s origin server has no way of knowing it in advance. But when Cloudflare renders a custom error page, the edge also writes that same Ray ID into the response body.&lt;/p&gt;

&lt;p&gt;So if the Ray ID from the response header appears in the body, and the body doesn’t match any default Cloudflare template, you’re looking at a custom error page from a paying customer.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_custom_error_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;response&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;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;600&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="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloudflare&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&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;server&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;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;ray_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cf-ray&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&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="mi"&gt;0&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;ray_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&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;default_markers&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;Attention Required! | Cloudflare&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;_cf_chl_opt&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;cf-error-details&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;__CF$cv$params&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;/cdn-cgi/challenge-platform/scripts/jsd/main.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;default_markers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One false positive trap: Cloudflare’s bot detection JS beacon also embeds the Ray ID in normal HTML responses. The &lt;code&gt;default_markers&lt;/code&gt; exclusion list catches this.&lt;/p&gt;

&lt;p&gt;To trigger the error page, hit a nonexistent API path: &lt;code&gt;https://api.example.com/api/v1/zzzz_not_real&lt;/code&gt;. APIs reliably return 4xx on unknown paths, which triggers Cloudflare’s error rendering. Marketing sites require probing paths like &lt;code&gt;/wp-admin&lt;/code&gt; or &lt;code&gt;/.env&lt;/code&gt; – more aggressive and more likely to get your scanner flagged.&lt;/p&gt;

&lt;p&gt;Running this against &lt;code&gt;api.*&lt;/code&gt; subdomains at scale, the hits were Swiss classifieds platforms, central banks, major retailers, government agencies. Exactly the profile you’d expect for paid customers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #5: Cloudflare Access (Zero Trust)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.cloudflare.com/zero-trust/products/access/" rel="noopener noreferrer"&gt;Cloudflare Access&lt;/a&gt; gates any web application behind a login screen, typically used to protect internal tooling: Grafana dashboards, GitLab instances, Jenkins, internal admin panels. In 2026 it’s also being used to lock down MCP servers.&lt;/p&gt;

&lt;p&gt;When you hit an Access-protected endpoint without a valid session, Cloudflare redirects to the customer’s team page on &lt;code&gt;cloudflareaccess.com&lt;/code&gt;. That redirect is the signal.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_cloudflare_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;http_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;follow_redirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&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;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;303&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;307&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;308&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="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloudflareaccess.com&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;response&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;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internal tooling subdomains follow predictable patterns. For each domain, probe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gitlab.&amp;lt;domain&amp;gt;
grafana.&amp;lt;domain&amp;gt;
jenkins.&amp;lt;domain&amp;gt;
internal.&amp;lt;domain&amp;gt;
admin.&amp;lt;domain&amp;gt;
wiki.&amp;lt;domain&amp;gt;
mcp.&amp;lt;domain&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most won’t resolve. Check the ones that do. Access has a free tier (up to 50 users) so it’s not a hard Enterprise gate, but the engineering investment of configuring Access policies and integrating an identity provider correlates strongly with paid usage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #6: OV or EV TLS Certificates
&lt;/h2&gt;

&lt;p&gt;This one requires understanding the three tiers of SSL certificate validation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DV (domain-validated)&lt;/strong&gt; is what every free service issues, including Cloudflare’s &lt;a href="https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/" rel="noopener noreferrer"&gt;Universal SSL&lt;/a&gt;. The certificate authority just checks you control the domain. Takes seconds. The cert subject contains only &lt;code&gt;CN=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OV (organization-validated)&lt;/strong&gt; requires the CA to verify your company is a real legal entity – business registration, phone verification, the works. Takes days. The company name is embedded in the cert subject: &lt;code&gt;O=&lt;/code&gt;, &lt;code&gt;L=&lt;/code&gt;, &lt;code&gt;ST=&lt;/code&gt;, &lt;code&gt;C=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EV (extended validation)&lt;/strong&gt; is OV with a deeper background check: jurisdiction, physical address, operational existence. Subject fields include &lt;code&gt;businessCategory&lt;/code&gt;, &lt;code&gt;serialNumber&lt;/code&gt;, &lt;code&gt;jurisdictionCountryName&lt;/code&gt;. Used primarily in regulated industries where compliance frameworks mandate it.&lt;/p&gt;

&lt;p&gt;The detection angle: &lt;strong&gt;Cloudflare cannot issue OV or EV certificates.&lt;/strong&gt; Universal SSL is DV only. So if a domain resolves to Cloudflare IPs but its certificate is OV or EV, the customer purchased a commercial cert and uploaded it via &lt;a href="https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/" rel="noopener noreferrer"&gt;Custom Certificates&lt;/a&gt; – a Business plan feature ($200/month minimum) used almost exclusively by Enterprise customers.&lt;/p&gt;

&lt;p&gt;You can identify certificate tiers programmatically via the &lt;code&gt;certificatePolicies&lt;/code&gt; OIDs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;2.23.140.1.2.1&lt;/code&gt; – DV&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2.23.140.1.2.2&lt;/code&gt; – OV&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2.23.140.1.1&lt;/code&gt; – EV
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cert_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_tls_cert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;has_ev_subject_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cert&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;2.23.140.1.1&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;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;policy_oids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EV&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;O=&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;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.23.140.1.2.2&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;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;policy_oids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_paid_cert&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="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cloudflare_ip_ranges&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_a&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="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cert_tier&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="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OV&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;EV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing against fendt.com: OV cert issued by DigiCert with &lt;code&gt;O=AGCO GmbH&lt;/code&gt;, served from Cloudflare IPs. AGCO is a $14B multinational – the finding makes sense. OV/EV on a Cloudflare-served domain is one of the strongest single signals for Enterprise status.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #7: Static IPs
&lt;/h2&gt;

&lt;p&gt;By default, Cloudflare is anycast. A single IP like &lt;code&gt;104.21.3.47&lt;/code&gt; could be serving thousands of completely unrelated domains simultaneously. The IP belongs to Cloudflare and is shared across their entire customer base.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/" rel="noopener noreferrer"&gt;Static IPs&lt;/a&gt; are an Enterprise-only feature where Cloudflare allocates IPs from their range exclusively to a single customer. Nothing else resolves to those IPs. Common in financial services and B2B SaaS where clients require stable IP addresses for firewall allowlisting.&lt;/p&gt;

&lt;p&gt;Detection requires aggregate data. Build a frequency map across your full domain dataset:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_static_ip_candidates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_cloudflare_domains&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ip_to_domains&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;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_cloudflare_domains&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;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_a&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cloudflare_ip_ranges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;ip_to_domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&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;domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Anycast IPs serve thousands of domains
&lt;/span&gt;    &lt;span class="c1"&gt;# Static IPs serve 1-3 (apex, www, maybe a subdomain)
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ip_to_domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&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="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional tell: Static IPs tend to be allocated in sequential blocks. If a single domain has two A records where only the third octet differs, and both are rare in your frequency map, that’s a strong Static IP signal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #8: Secondary DNS
&lt;/h2&gt;

&lt;p&gt;One of the cleanest Enterprise signals and the easiest to detect.&lt;/p&gt;

&lt;p&gt;Standard Cloudflare customers let Cloudflare host their DNS entirely – nameservers become &lt;code&gt;ns1.cloudflare.com&lt;/code&gt; and &lt;code&gt;ns2.cloudflare.com&lt;/code&gt;. Secondary DNS is a different model: the customer keeps their own primary DNS infrastructure and adds Cloudflare as a secondary authoritative server, receiving zone transfers via AXFR/IXFR as a resilient backup.&lt;/p&gt;

&lt;p&gt;The NS records tell the story immediately. A Secondary DNS customer has both their own nameservers and Cloudflare’s secondary ones listed together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ns1.company.com
ns2.company.com
ns0227.secondary.cloudflare.com
ns0022.secondary.cloudflare.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;*.secondary.cloudflare.com&lt;/code&gt; pattern only ever appears for this product. The four-digit number is a per-customer or per-zone identifier.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_cloudflare_secondary_dns&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="n"&gt;ns_records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dns_lookup_ns&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;secondary.cloudflare.com&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;ns&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ns_records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per &lt;a href="https://developers.cloudflare.com/dns/reference/all-features/" rel="noopener noreferrer"&gt;Cloudflare’s DNS feature matrix&lt;/a&gt;, Secondary DNS requires Enterprise plus the &lt;strong&gt;Foundation DNS&lt;/strong&gt; add-on specifically – it’s not included in a standard Enterprise contract. That makes it a stronger indicator than most Enterprise features. Organizations running Secondary DNS have made a deliberate investment in DNS as critical infrastructure.&lt;/p&gt;

&lt;p&gt;The IRS has it configured. Government agencies, central banks, and large financial institutions are the profile to expect when scanning for this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signal #9: Magic Transit (BGP)
&lt;/h2&gt;

&lt;p&gt;Every other signal on this list works by inspecting a single domain. This one works differently – you’re looking at public BGP routing tables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cloudflare.com/network-services/products/magic-transit/" rel="noopener noreferrer"&gt;Magic Transit&lt;/a&gt; lets Enterprise customers route their own IP space through Cloudflare’s network. The customer brings IP prefixes they own (or lease), and Cloudflare announces those prefixes to the internet from AS13335. All traffic destined for those IPs flows through Cloudflare’s scrubbing infrastructure before reaching the customer’s network.&lt;/p&gt;

&lt;p&gt;The detection approach: pull every prefix currently announced by AS13335, then WHOIS each one. Prefixes registered to non-Cloudflare organizations are Magic Transit customers.&lt;/p&gt;

&lt;p&gt;Browse it manually first to validate the concept:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bgp.he.net/AS13335#_prefixes" rel="noopener noreferrer"&gt;https://bgp.he.net/AS13335#_prefixes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For programmatic detection, RIPE stat is the most reliable data source:&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;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_as13335_prefixes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;r&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS13335&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Skip IPv6 -- Magic Transit customers are almost exclusively IPv4
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&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;data&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;prefixes&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prefix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="n"&gt;NOISE_PATTERNS&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;ip-ripe&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;ip manager&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;-mnt&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;private customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;CLOUDFLARE_HANDLES&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;CLOUD14&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;CLOUDF&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;NOISE_HANDLES&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;ripe&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;arin&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;apnic&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;afrinic&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;lacnic&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;find_magic_transit_customers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefixes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;customers&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;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;prefixes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prefix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;org&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;whois_org&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ARIN RDAP with redirect following
&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;org&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;is_noise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org&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="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;handle&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;customers&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;prefix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prefix&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;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;org&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bgpview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://bgpview.io/prefix/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prefix&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="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this against the full AS13335 prefix list surfaces names like these:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Organization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;23.227.37.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shopify, Inc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;199.68.19.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VISA International Service Association&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;131.167.255.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Battelle Memorial Institute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;161.248.134.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Canadian Association of Blue Cross Plans&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;203.15.65.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;University of Sydney&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;103.77.7.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FUJIFILM Data Management Solutions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;351.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Genetec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2109&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yardi Systems, Inc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things to filter out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ISPs and carriers&lt;/strong&gt; use Magic Transit for their own DDoS protection – it’s actually one of Cloudflare’s largest use cases by traffic volume. Skip anything whose org name or netname contains &lt;code&gt;ISP&lt;/code&gt;, &lt;code&gt;TELECOM&lt;/code&gt;, &lt;code&gt;CARRIER&lt;/code&gt;, or &lt;code&gt;DATACENTER&lt;/code&gt;, or anything that has its own ASN with a large prefix count. Legitimate enterprise Magic Transit customers typically have one or two prefixes total and no BGP presence of their own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHOIS placeholders&lt;/strong&gt; – entries showing as &lt;code&gt;IP-RIPE&lt;/code&gt;, &lt;code&gt;IP Manager&lt;/code&gt;, or handles ending in &lt;code&gt;-MNT&lt;/code&gt; are administrative placeholders or IP broker records, not end customers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IP leasing&lt;/strong&gt; – some customers bring leased IP space rather than IPs they own outright. The WHOIS points to the leasing company (IPXO is common). The tell is &lt;code&gt;mnt-lower: IPXO-MNT&lt;/code&gt; in the RIPE record.&lt;/p&gt;

&lt;p&gt;After filtering, what remains is unambiguously Enterprise-tier. Magic Transit requires a dedicated sales engagement, a minimum committed bandwidth, and a manual BGP peering session with Cloudflare’s network team. You don’t stumble into it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Watch Out For
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Platform contamination.&lt;/strong&gt; Hosting platforms like Kinsta run all customer sites through Cloudflare Enterprise by default. The tenant didn’t configure it, may not know it’s there, and isn’t a Cloudflare customer in any meaningful sense. This is part of why stacking paid signals matters – a Kinsta-hosted blog won’t have a custom error page or an OV cert or Cloudflare Access configured.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scale carefully.&lt;/strong&gt; Probing endpoints with WAF-triggering patterns (SQLi strings, common exploit paths) across thousands of domains will get your scanner blocked fast. Everything in this list can be detected with benign requests – non-existent paths, standard User-Agents, no exotic payloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&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;Plan&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IP / NS check&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;DNS lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard SSO TXT&lt;/td&gt;
&lt;td&gt;Free (high friction)&lt;/td&gt;
&lt;td&gt;DNS TXT lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Routing&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;MX record lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bot cookies (&lt;code&gt;__cf_bm&lt;/code&gt;, &lt;code&gt;_cfuvid&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Pro+&lt;/td&gt;
&lt;td&gt;Passive HTTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom error pages&lt;/td&gt;
&lt;td&gt;Pro+ ($25/mo)&lt;/td&gt;
&lt;td&gt;HTTP probe + body parse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Security (Area 1)&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;MX record lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Access&lt;/td&gt;
&lt;td&gt;Free tier (strong proxy)&lt;/td&gt;
&lt;td&gt;HTTP redirect check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OV/EV certificate&lt;/td&gt;
&lt;td&gt;Business+ ($200/mo)&lt;/td&gt;
&lt;td&gt;TLS cert inspection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static IPs&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;Aggregate DNS map&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secondary DNS&lt;/td&gt;
&lt;td&gt;Enterprise + Foundation DNS&lt;/td&gt;
&lt;td&gt;NS record lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Magic Transit&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;BGP + WHOIS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of these signals is definitive in isolation. Stack them and you get a surprisingly clear picture of where a company actually sits on the Cloudflare tier ladder – all from public data, no credentials required.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Spotted a signal I missed? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>networking</category>
      <category>python</category>
      <category>security</category>
    </item>
    <item>
      <title>I analyzed 100K HubSpot customers - here's what I learned</title>
      <dc:creator>Henley Wing</dc:creator>
      <pubDate>Sat, 04 Apr 2026 21:18:29 +0000</pubDate>
      <link>https://dev.to/henley_wing_9424eb9a3177c/i-analyzed-100k-hubspot-customers-heres-what-i-learned-32a1</link>
      <guid>https://dev.to/henley_wing_9424eb9a3177c/i-analyzed-100k-hubspot-customers-heres-what-i-learned-32a1</guid>
      <description>&lt;p&gt;If you work at a HubSpot agency, build &lt;a href="https://ecosystem.hubspot.com/marketplace/apps" rel="noopener noreferrer"&gt;apps on the HubSpot platform&lt;/a&gt;, or just want to understand who actually uses HubSpot and how, this article is for you.&lt;/p&gt;

&lt;p&gt;I started with the customer list published by &lt;a href="https://bloomberry.com/data/hubspot/" rel="noopener noreferrer"&gt;Bloomberry&lt;/a&gt;, which tracks 108,269 companies running HubSpot. They find these companies by scanning DNS records, the technical config files every company publishes when they set up an email or web tool.&lt;/p&gt;

&lt;p&gt;HubSpot leaves specific fingerprints in those records: &lt;a href="https://knowledge.hubspot.com/marketing-email/manage-email-authentication-in-hubspot" rel="noopener noreferrer"&gt;SPF entries&lt;/a&gt; that authorize HubSpot to send email on a company's behalf, CNAME records pointing to HubSpot-hosted subdomains, and tracking pixels tied to HubSpot's servers. If a company is running HubSpot, those records don't lie. I took that raw list and dug in.&lt;/p&gt;

&lt;p&gt;Here's what the data shows.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Software companies use HubSpot at nearly 10x the average rate.
&lt;/h2&gt;

&lt;p&gt;Ranking by raw customer count is boring. Software Development comes first, then IT Services, then Financial Services. That just tells you which industries have a lot of companies in general.&lt;/p&gt;

&lt;p&gt;The more useful metric is a multiplier: compared to all 2 million domains in the dataset, how much more likely is a company in a given industry to be running HubSpot?&lt;/p&gt;

&lt;p&gt;Software Development comes in at 9.6x. A software company is nearly ten times more likely to be on HubSpot than the average business. Almost every software company that does marketing eventually ends up here.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The other over-indexing industries are more surprising than you'd expect.
&lt;/h2&gt;

&lt;p&gt;After software, the industries most disproportionately likely to use HubSpot are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Market Research (5.8x).&lt;/strong&gt; Their entire business is built on educating buyers and building credibility over time. HubSpot's content and nurture tools are a natural fit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E-Learning (4.9x).&lt;/strong&gt; These companies attract, educate, and convert prospects over long consideration cycles. That's textbook inbound marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Financial Services (4.4x).&lt;/strong&gt; Fintech skews this up, but traditional financial services firms are in the mix too. Compliance constraints limit many channels, pushing companies toward owned tools like HubSpot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Medical Equipment (3.9x) and Biotech (3.7x).&lt;/strong&gt; Both sell through long, relationship-driven cycles to hospitals and procurement committees. A deal that takes 18 months and involves six stakeholders is exactly what HubSpot is built for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marketing and Advertising Services (3.5x each).&lt;/strong&gt; Agencies use the tools they recommend to clients. HubSpot's partner program also gives certified agencies referral revenue, making adoption a business decision as much as a product one.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The typical HubSpot customer is smaller than most people assume.
&lt;/h2&gt;

&lt;p&gt;The single biggest segment, at 42% of all users, is companies with 11 to 50 employees. Companies with fewer than 200 employees account for 86% of the entire customer base. Past 200 employees, adoption drops off as companies move toward Marketo or Salesforce Marketing Cloud.&lt;/p&gt;

&lt;p&gt;The breakdown looks very different depending on which HubSpot product you're looking at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free CRM.&lt;/strong&gt; 78% of users have fewer than 10 employees. This is not a customer base. It's a top-of-funnel acquisition strategy: get millions of tiny businesses in the door, convert the ones that grow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Hub&lt;/strong&gt; (helpdesk, live chat, knowledge base). Over half of users have fewer than 10 employees. At that scale it usually means one chat widget and a basic help center. Only 4 companies with more than 10,000 employees use it at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Hub&lt;/strong&gt; (websites, landing pages, blogs). The most even spread of any product. Website needs exist at every company size, so the distribution is flatter across the board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sales Hub&lt;/strong&gt; (CRM, pipelines, deals). Reaches furthest up the size curve. The tail at larger companies is healthier than any other HubSpot product, and 0.8% of Sales Hub users have more than 10,000 employees, compared to just 0.1% for Service Hub.&lt;/p&gt;

&lt;p&gt;If you're selling to HubSpot customers, the specific product they run is one of the best signals you have about their size.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. HubSpot has genuinely caught Salesforce in the mid-market.
&lt;/h2&gt;

&lt;p&gt;I polled 972 sales leaders in March 2026 with one question: what is your company's main CRM?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.salesforce.com" rel="noopener noreferrer"&gt;Salesforce&lt;/a&gt; came in at 43% (419 companies). HubSpot at 41% (397 companies). Twenty-two companies separated them. At that sample size, that is a statistical tie.&lt;/p&gt;

&lt;p&gt;A decade ago this wasn't close. Salesforce was the default for any company that took sales seriously, and HubSpot was a marketing tool with a free CRM bolted on. That is no longer the case.&lt;/p&gt;

&lt;p&gt;Real companies in the poll running HubSpot as their primary CRM include Zapier, Bitwarden, GitKraken, CoinGecko, DataSnipper, UpGuard, Unstructured, and Rinsed. These are not small companies kicking the tires. They are funded, growing businesses with real sales teams operating entirely out of HubSpot.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. HubSpot and Salesforce are not fighting over the same customers anymore.
&lt;/h2&gt;

&lt;p&gt;The near-tie masks something more interesting: the two platforms have quietly split into different markets.&lt;/p&gt;

&lt;p&gt;HubSpot wins at companies with faster sales cycles, technical buyers, and self-serve growth motions. Businesses where a prospect can sign up, try the product, and convert without ever talking to a sales rep. Bitwarden, Unstructured, Flowcode, and Rinsed all fit this profile.&lt;/p&gt;

&lt;p&gt;Salesforce wins where deals are complex, contracts are large, and buying involves multiple departments over months. Rippling, Toast, Notion, Superhuman, and Betterment are all in that camp. These are businesses where the CRM needs deep customization and a dedicated admin team.&lt;/p&gt;

&lt;p&gt;They're both called CRMs. They're serving increasingly different businesses. That matters a lot if you're an agency deciding which platform to specialize in.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Finland uses HubSpot more than any other country.
&lt;/h2&gt;

&lt;p&gt;The US has the most HubSpot users in absolute terms at 48,289 companies. But adjusted for how many total businesses exist in each country, the rankings look very different.&lt;/p&gt;

&lt;p&gt;Finnish companies are 5.9x more likely to be running HubSpot than average. Norway is at 5.1x. New Zealand at 4.6x. The US at 4.2x. Australia at 4.1x. Sweden, Denmark, and Belgium all make the top 15.&lt;/p&gt;

&lt;p&gt;The Nordics showing up this heavily is striking. Small markets by population, but they produce a disproportionate number of tech-forward businesses that adopt modern marketing tools early.&lt;/p&gt;

&lt;p&gt;Japan at 5.1x is the most surprising entry. American B2B SaaS tools typically struggle there due to language barriers and a preference for domestic software. Japan tying Norway suggests HubSpot has made inroads that most US software companies never manage.&lt;/p&gt;

&lt;p&gt;Israel at 3.9x makes complete sense. One of the densest startup ecosystems in the world relative to population. Israeli startups adopt modern go-to-market tools early and HubSpot benefits from that disproportionately.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. HubSpot is third in email marketing by domain count, and that's actually a compliment.
&lt;/h2&gt;

&lt;p&gt;I looked at which email marketing tool each of the 2 million domains in the dataset was configured to use, by reading DNS records. The breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://bloomberry.com/data/mailchimp/" rel="noopener noreferrer"&gt;Mailchimp&lt;/a&gt;: 41.8%&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.brevo.com" rel="noopener noreferrer"&gt;Brevo&lt;/a&gt;: 16%&lt;/li&gt;
&lt;li&gt;HubSpot: 15.1%&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.klaviyo.com" rel="noopener noreferrer"&gt;Klaviyo&lt;/a&gt;: 13.1%&lt;/li&gt;
&lt;li&gt;Constant Contact: 4.3%&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pardot.com" rel="noopener noreferrer"&gt;Pardot&lt;/a&gt;: 3.9%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Third place sounds like a demotion. It isn't. Mailchimp and Brevo users are often just sending a monthly newsletter. HubSpot customers are typically running their entire marketing operation through the platform: forms, landing pages, ad tracking, CRM, chat, support, and email all wired together. Third by domain count likely means first by revenue per customer.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Brevo is the story most people in the HubSpot world are ignoring.
&lt;/h2&gt;

&lt;p&gt;16% market share. More customers than HubSpot by raw count. And it barely registers in most marketing technology conversations.&lt;/p&gt;

&lt;p&gt;Brevo rebranded from Sendinblue in 2023 and has been quietly winning on price. It costs considerably less than HubSpot at almost every tier. A lot of companies land on Brevo when they outgrow Mailchimp but can't justify HubSpot's pricing, particularly in European and Latin American markets.&lt;/p&gt;

&lt;p&gt;For HubSpot agencies and developers, this matters. Brevo represents a large pool of companies that opted out of HubSpot specifically because of cost. They're not on Salesforce. They're one clear value conversation away from switching.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;108,269 companies are running HubSpot. It's statistically tied with Salesforce in the mid-market. Software companies adopt it at nearly 10x the average rate. The typical customer is an 11 to 50 person company, probably in tech, probably in the US or Northern Europe.&lt;/p&gt;

&lt;p&gt;If you're a HubSpot agency, the clearest opportunity is in industries that over-index but aren't obvious: medical equipment, biotech, financial services. Complex buying cycles, real budget, and not yet heavily targeted by HubSpot-specialized agencies.&lt;/p&gt;

&lt;p&gt;If you're a developer building on the platform, Sales Hub and Content Hub users skew larger and are worth approaching differently than Service Hub users.&lt;/p&gt;

&lt;p&gt;And if you're just trying to understand the landscape: HubSpot is no longer a marketing tool with a CRM attached. It's a full business platform, and the data backs that up.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>datascience</category>
      <category>marketing</category>
      <category>saas</category>
    </item>
    <item>
      <title>How to Find Any Company's Tech Stack (A Developer's Guide)</title>
      <dc:creator>Henley Wing</dc:creator>
      <pubDate>Sat, 21 Feb 2026 16:33:24 +0000</pubDate>
      <link>https://dev.to/henley_wing_9424eb9a3177c/how-to-find-any-companys-tech-stack-a-developers-guide-53h7</link>
      <guid>https://dev.to/henley_wing_9424eb9a3177c/how-to-find-any-companys-tech-stack-a-developers-guide-53h7</guid>
      <description>&lt;p&gt;Let me be upfront about why most tech stack tools are kind of useless for developers.&lt;/p&gt;

&lt;p&gt;Tools like Wappalyzer and BuiltWith scrape cookies, meta tags, and frontend JavaScript. They'll tell you a company uses React and Google Analytics. Cool. But you probably already guessed that. &lt;/p&gt;

&lt;p&gt;What you actually want to know is: &lt;em&gt;what does their backend look like?&lt;/em&gt; What's their data infrastructure?  Do they use Datadog or Grafana for observability? What does their auth layer look like?&lt;/p&gt;

&lt;p&gt;That information doesn't show up in a browser. It lives in DNS records, HTTP headers, subdomains, job postings, and public repos. And you can get all of it for free if you know where to look.&lt;/p&gt;

&lt;p&gt;This guide is organized by depth — starting with the most technical, developer-specific methods and working toward the simpler passive ones. Skip to whatever level you need.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Part 1: Infrastructure Recon (Get your hands dirty)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Inspect API response headers with curl&lt;/li&gt;
&lt;li&gt;2. Extract third-party domains from network calls&lt;/li&gt;
&lt;li&gt;3. Read Content Security Policy headers&lt;/li&gt;
&lt;li&gt;4. Enumerate subdomains and trace them to cloud providers&lt;/li&gt;
&lt;li&gt;5. Search Cisco Umbrella DNS traffic logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Passive Signals (High signal, zero effort)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;6. Look up DNS TXT records&lt;/li&gt;
&lt;li&gt;7. Check their GitHub, NPM, and Hugging Face orgs&lt;/li&gt;
&lt;li&gt;8. Read subprocessor lists and trust centers&lt;/li&gt;
&lt;li&gt;9. Check their status page&lt;/li&gt;
&lt;li&gt;10. Mine historical job postings&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Part 1: Infrastructure Recon
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Inspect API response headers with curl
&lt;/h3&gt;

&lt;p&gt;This is the fastest technique in this entire guide for developers. Most companies expose an API at a predictable URL — &lt;code&gt;api.company.com&lt;/code&gt; or &lt;code&gt;api.company.io&lt;/code&gt;. You don't need credentials. Just hit it and read what comes back.&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;-sI&lt;/span&gt; https://api.company.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even a 401, 403, or 404 response is packed with information. The infrastructure fingerprints itself in the headers.&lt;/p&gt;

&lt;p&gt;Here's what you're looking for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&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;&lt;code&gt;Apigw-Requestid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AWS API Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Amzn-RequestId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AWS Lambda / API Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Cache: Hit from cloudfront&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AWS CloudFront CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Kong-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kong API Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Azure-Ref&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Azure API Management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Server: AkamaiGHost&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Akamai CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Server: cloudflare&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Server: openresty&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nginx-based (common with Kong)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Powered-By: Express&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Node.js + Express&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-MuleSoft-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MuleSoft API management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Apigee-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Google Apigee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Server: Mashery Proxy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mashery/TIBCO API management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x-envoy-upstream-service-time&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Envoy proxy (often means Istio service mesh)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Via: 1.1 vegur&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Heroku routing layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x-vercel-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vercel deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x-render-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Render deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Running &lt;code&gt;curl -sI https://api.utilimarc.com/&lt;/code&gt; returns a 404, but the &lt;code&gt;Apigw-Requestid&lt;/code&gt; header is a dead giveaway for AWS API Gateway. The &lt;code&gt;Apigw-&lt;/code&gt; prefix is specific to AWS — no other provider uses it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go further:&lt;/strong&gt; Also try &lt;code&gt;curl -sI https://company.com&lt;/code&gt; to check their web infra. The CDN, load balancer, and sometimes even the backend framework leak through the top-level domain's headers too.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Extract third-party domains from network calls
&lt;/h3&gt;

&lt;p&gt;Every page load is a treasure map. The browser fetches scripts, fonts, pixels, and analytics from dozens of third-party services — all of which have unique hostnames that identify the vendor.&lt;/p&gt;

&lt;p&gt;Open Chrome DevTools (F12), go to the Console tab, and run:&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="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&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="s2"&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="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hostname&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="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="nb"&gt;Boolean&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="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you every distinct third-party hostname loaded by the page, deduplicated and sorted, with the first-party domain filtered out.&lt;/p&gt;

&lt;p&gt;What you'll typically find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observability:&lt;/strong&gt; &lt;code&gt;browser-intake.datadoghq.com&lt;/code&gt;, &lt;code&gt;ingest.sentry.io&lt;/code&gt;, &lt;code&gt;rs.fullstory.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature flags:&lt;/strong&gt; &lt;code&gt;app.launchdarkly.com&lt;/code&gt;, &lt;code&gt;events.split.io&lt;/code&gt;, &lt;code&gt;featureflags.statsig.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B testing:&lt;/strong&gt; &lt;code&gt;api.eppo.cloud&lt;/code&gt;, &lt;code&gt;cdn.optimizely.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN/infra:&lt;/strong&gt; &lt;code&gt;cdn.company.cloudfront.net&lt;/code&gt; (CloudFront), &lt;code&gt;*.fastly.net&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth:&lt;/strong&gt; &lt;code&gt;company.auth0.com&lt;/code&gt;, &lt;code&gt;cognito-idp.*.amazonaws.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging/metrics:&lt;/strong&gt; &lt;code&gt;logs.browser-intake-datadoghq.com&lt;/code&gt;, &lt;code&gt;api.honeycomb.io&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Do this on the authenticated app (&lt;code&gt;app.company.com&lt;/code&gt;), not just the marketing site. The marketing page is often a static site or different stack entirely. The actual product is where the interesting infra shows up — real-time event pipelines, feature flagging, product analytics, the works.&lt;/p&gt;

&lt;p&gt;Paste the hostname list into an LLM and ask it to map each domain to a product. This is faster and more up-to-date than any static tool, since new vendor domains get recognized immediately.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Read Content Security Policy headers
&lt;/h3&gt;

&lt;p&gt;CSP is a security feature that tells browsers which domains a site is allowed to load resources from or send data to. But for your purposes, it's a complete manifest of vendor integrations — because if a domain is in the CSP, the app is explicitly using it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to find it:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Chrome DevTools → Network tab&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Preserve log&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Reload and click around the app&lt;/li&gt;
&lt;li&gt;Filter by &lt;strong&gt;Fetch/XHR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click any request → &lt;strong&gt;Headers&lt;/strong&gt; → look for &lt;code&gt;Content-Security-Policy&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The CSP will be a long string of directives like &lt;code&gt;connect-src&lt;/code&gt;, &lt;code&gt;script-src&lt;/code&gt;, and &lt;code&gt;img-src&lt;/code&gt;, each followed by a list of allowed domains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example from Monday.com's CSP:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;monday.zendesk.com&lt;/code&gt; → uses Zendesk for support&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;monday.lightning.force.com&lt;/code&gt; → Salesforce integration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;monday.vitally.io&lt;/code&gt; → Vitally for CS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;o474786.ingest.sentry.io&lt;/code&gt; → &lt;strong&gt;Sentry&lt;/strong&gt; for error tracking&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*.launchdarkly.com&lt;/code&gt; → &lt;strong&gt;LaunchDarkly&lt;/strong&gt; for feature flags&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.datadoghq.com&lt;/code&gt; → &lt;strong&gt;Datadog&lt;/strong&gt; for observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy the entire CSP value and throw it into an LLM: &lt;em&gt;"What developer tools and SaaS products correspond to these domains in this Content Security Policy?"&lt;/em&gt; You'll get a categorized breakdown in seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Not every site sets a CSP, and CSPs are sometimes set only on certain responses. If you don't see it, move on — but when it's there, it's one of the most explicit tech signals available.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Enumerate subdomains and trace them to cloud providers
&lt;/h3&gt;

&lt;p&gt;Companies don't run everything on &lt;code&gt;www&lt;/code&gt;. As infrastructure grows, services get their own subdomains — owned by different teams, deployed independently, with separate access controls. And they're often named &lt;em&gt;very&lt;/em&gt; literally.&lt;/p&gt;

&lt;p&gt;A subdomain called &lt;code&gt;kafka-prod-b2.company.com&lt;/code&gt; tells you exactly what's running there. Same for &lt;code&gt;elastic.company.com&lt;/code&gt;, &lt;code&gt;grafana.internal.company.com&lt;/code&gt;, or &lt;code&gt;consul.company.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding subdomains:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The easiest free option is &lt;a href="https://pentest-tools.com" rel="noopener noreferrer"&gt;pentest-tools.com&lt;/a&gt; — they give you two free reports, which is enough for a research session. Enter the domain and get a list of discovered subdomains.&lt;/p&gt;

&lt;p&gt;For a command-line approach, &lt;a href="https://github.com/owasp-amass/amass" rel="noopener noreferrer"&gt;Amass&lt;/a&gt; is the gold standard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;amass enum &lt;span class="nt"&gt;-passive&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; company.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use &lt;a href="https://github.com/projectdiscovery/subfinder" rel="noopener noreferrer"&gt;subfinder&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;subfinder &lt;span class="nt"&gt;-d&lt;/span&gt; company.com &lt;span class="nt"&gt;-silent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real example — Nokia's subdomains:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;elastic0.cbrs.iot.nokia.com         → Elasticsearch
kafka-prod-b2.enso.saas.nokia.com   → Kafka in production
pfsense.iot.nokia.com               → pfSense firewall
grafana.cbrs.iot.nokia.com          → Grafana dashboards
consul.cbrs.iot.nokia.com           → HashiCorp Consul
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just reading the names: they're running an ELK-adjacent stack with Kafka for streaming, Consul for service discovery, and Grafana for dashboards. That's a detailed architecture picture without touching a single line of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trace subdomains to cloud providers:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you have a list, run &lt;code&gt;dig&lt;/code&gt; on interesting ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short kafka-prod-b2.enso.saas.nokia.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then look up the IP in a tool like &lt;a href="https://ipinfo.io" rel="noopener noreferrer"&gt;ipinfo.io&lt;/a&gt; or just check the PTR record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short &lt;span class="nt"&gt;-x&lt;/span&gt; &amp;lt;IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it resolves to &lt;code&gt;*.compute.amazonaws.com&lt;/code&gt; → AWS. &lt;code&gt;*.googleusercontent.com&lt;/code&gt; → GCP. &lt;code&gt;*.azure.com&lt;/code&gt; → Azure. Repeat across a few subdomains and you'll quickly see which cloud(s) they're on. Many large companies are multi-cloud, and the subdomain patterns often tell you which workloads live where.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Search Cisco Umbrella DNS traffic logs
&lt;/h3&gt;

&lt;p&gt;This one is genuinely underused and feels like a cheat code.&lt;/p&gt;

&lt;p&gt;Cisco Umbrella (formerly OpenDNS) operates one of the world's largest DNS resolver networks. Every day, they publish the top 1 million most queried domains and subdomains through their infrastructure — the &lt;strong&gt;Cisco Umbrella Popularity List&lt;/strong&gt;. It's free, public, and updated daily.&lt;/p&gt;

&lt;p&gt;Why this is different from subdomain enumeration: enumeration tools find subdomains that &lt;em&gt;exist&lt;/em&gt;. The Umbrella list shows subdomains that are &lt;em&gt;actively being used&lt;/em&gt;, based on real DNS traffic. This means you'll catch third-party SaaS tools with company-specific subdomains that would never appear in a passive scan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download and search it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download&lt;/span&gt;
curl &lt;span class="nt"&gt;-O&lt;/span&gt; http://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip
unzip top-1m.csv.zip

&lt;span class="c"&gt;# Search for a company&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"autodesk"&lt;/span&gt; top-1m.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or do it in Python:&lt;/strong&gt;&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="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;autodesk&lt;/span&gt;&lt;span class="sh"&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;top-1m.csv&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;reader&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="nf"&gt;reader&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;rank&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&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;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;matches&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;Rank &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rank&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What I found when searching for "autodesk":&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;autodeskfeedback.az1.qualtrics.com     → Qualtrics for surveys
autodesk.enterprise.slack.com          → Slack Enterprise Grid
autodesk.pagerduty.com                 → PagerDuty for incident management
autodeskglobal.okta.com                → Okta for identity/SSO
autodeskglobal-ssl.mktoweb.com         → Marketo for marketing automation
autodesk.splunkcloud.com               → Splunk for log analysis
*.autodesk.com.edgekey.net             → Akamai CDN
notifications.api.autodesk.com         → Dedicated notifications microservice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From one grep, you can see their incident management stack (PagerDuty), their identity provider (Okta), their SIEM (Splunk), and their CDN (Akamai). Paid technographic tools almost never surface these, because they focus on frontend detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; This only works for companies with enough external traffic to appear in the top million. Smaller startups likely won't show up. But for anything mid-size or larger, it's one of the highest-signal free techniques available.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Passive Signals
&lt;/h2&gt;

&lt;p&gt;These methods require less technical effort but often reveal tools that the recon techniques above will completely miss — especially backend business tooling, internal SaaS, and vendor relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Look up DNS TXT records
&lt;/h3&gt;

&lt;p&gt;When a SaaS tool needs to verify domain ownership for SSO or SAML integration, they require you to add a TXT record to DNS. These records persist long after the integration is live. They're public, unfakeable, and one of the strongest signals that a company actually uses a product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command line:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig TXT company.com +short
&lt;span class="c"&gt;# Or for more detail:&lt;/span&gt;
dig TXT company.com ANY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or use a GUI:&lt;/strong&gt; &lt;a href="https://dnschecker.org" rel="noopener noreferrer"&gt;dnschecker.org&lt;/a&gt; → choose "TXT" record type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example — OpenAI's TXT records reveal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notion-domain-verification=...        → Notion
atlassian-domain-verification=...     → Jira / Confluence
docker-verification=...               → Docker Hub
postman-domain-verification=...       → Postman
ms-domain-verification=...            → Azure AD / M365
miro-verification=...                 → Miro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other dev-tool-related patterns to look for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TXT record prefix&lt;/th&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Docker Hub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;postman-domain-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Postman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;atlassian-domain-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jira, Confluence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stripe-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stripe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;datadog-...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Datadog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pagerduty-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PagerDuty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;github-challenge-...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GitHub Enterprise / SSO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1password-site-verification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1Password Teams&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sentry-...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sentry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;linear-...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If a verification record exists, someone on the IT or infra team had to explicitly add it. That's a confirmed active integration.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Check their GitHub, NPM, and Hugging Face orgs
&lt;/h3&gt;

&lt;p&gt;Takes about 60 seconds and often reveals the most direct, unambiguous evidence of what a company actually builds with.&lt;/p&gt;

&lt;h4&gt;
  
  
  GitHub
&lt;/h4&gt;

&lt;p&gt;Start at &lt;code&gt;github.com/{company-name}&lt;/code&gt;. Even if it's not linked from their website, it's usually guessable. Try the obvious names.&lt;/p&gt;

&lt;p&gt;What to look at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Language breakdown:&lt;/strong&gt; GitHub shows a bar graph of languages across public repos. 40 repos in Go? That's a Go shop. Python-heavy with some Rust? That's a signal too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo names:&lt;/strong&gt; Companies often open-source internal tooling, SDKs, and infrastructure modules. Names like &lt;code&gt;company-terraform-modules&lt;/code&gt;, &lt;code&gt;company-kafka-consumer&lt;/code&gt;, or &lt;code&gt;company-k8s-operators&lt;/code&gt; are literal descriptions of their infra.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency files:&lt;/strong&gt; Open any repo and check:&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;# Node projects&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;package.json | jq &lt;span class="s1"&gt;'.dependencies, .devDependencies'&lt;/span&gt;

&lt;span class="c"&gt;# Python projects  &lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;requirements.txt
&lt;span class="nb"&gt;cat &lt;/span&gt;pyproject.toml

&lt;span class="c"&gt;# Go projects&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;go.mod

&lt;span class="c"&gt;# Ruby&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;Gemfile

&lt;span class="c"&gt;# Java/Kotlin&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;build.gradle
&lt;span class="nb"&gt;cat &lt;/span&gt;pom.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to understand the code. Just read the dependency names. A Python repo importing &lt;code&gt;pyspark&lt;/code&gt;, &lt;code&gt;delta-spark&lt;/code&gt;, and &lt;code&gt;airflow&lt;/code&gt; tells you their data engineering stack. A Node repo pulling in &lt;code&gt;@opentelemetry/api&lt;/code&gt; tells you they're doing structured observability with OpenTelemetry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions workflows:&lt;/strong&gt; This is often overlooked. Check &lt;code&gt;.github/workflows/&lt;/code&gt; in any repo. The workflow YAML files show their CI/CD setup, which testing tools they use, and what cloud they deploy to:&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;# Look for things like:&lt;/span&gt;
&lt;span class="c"&gt;# - uses: aws-actions/configure-aws-credentials  → AWS&lt;/span&gt;
&lt;span class="c"&gt;# - uses: google-github-actions/auth             → GCP&lt;/span&gt;
&lt;span class="c"&gt;# - uses: hashicorp/setup-terraform              → Terraform&lt;/span&gt;
&lt;span class="c"&gt;# - uses: docker/build-push-action               → Docker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  NPM
&lt;/h4&gt;

&lt;p&gt;Search &lt;code&gt;npmjs.com&lt;/code&gt; for the company name, or try &lt;code&gt;npmjs.com/~{org-name}&lt;/code&gt;. Published packages reveal the frontend frameworks they use and what internal tools they've built and open-sourced. A company publishing a design system built on React and Storybook tells you a lot about their frontend stack.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hugging Face
&lt;/h4&gt;

&lt;p&gt;Head to &lt;code&gt;huggingface.co/{company-name}&lt;/code&gt;. Useful for any company doing ML work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Models:&lt;/strong&gt; What architectures are they using? Fine-tuning on what base models?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Datasets:&lt;/strong&gt; What kind of data do they work with?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spaces:&lt;/strong&gt; Demo apps that show their framework choices (Gradio, Streamlit, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team size:&lt;/strong&gt; The member count gives a rough sense of ML team scale.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  8. Read subprocessor lists and trust centers
&lt;/h3&gt;

&lt;p&gt;Companies that handle personal data — especially for EU customers — are often legally required to disclose every third-party service that touches that data. These are &lt;strong&gt;subprocessors&lt;/strong&gt;, and the lists get published in "Trust Center" or "Security" pages.&lt;/p&gt;

&lt;p&gt;For developers, this is the fastest way to find out what SaaS infra a company is paying for: cloud providers, auth platforms, monitoring tools, data platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to find them:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google: "[company name] subprocessors"
Google: "[company name] trust center"
Look: footer links labeled "Trust," "Security," or "Privacy"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example from NewDays.ai's Trust Center:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just from one screenshot, you can confirm: AWS for cloud, Auth0 for authentication, Sentry for error monitoring. That's three confirmed infrastructure choices in 30 seconds.&lt;/p&gt;

&lt;p&gt;If the list is long, paste it into an LLM and ask it to group by function: &lt;em&gt;"Here is a subprocessor list. Categorize each vendor by function: cloud infrastructure, auth/identity, observability, data storage, CI/CD, etc."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not every company publishes one. But when they do, it's the most honest signal available — it's literally a receipt of their operational stack.&lt;/p&gt;




&lt;h3&gt;
  
  
  9. Check their status page
&lt;/h3&gt;

&lt;p&gt;Status pages (&lt;code&gt;status.company.com&lt;/code&gt;, or hosted on Atlassian Statuspage, Instatus, or Better Uptime) are designed for customer communication. But they contain two things that are valuable for tech recon:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The components list reveals architecture.&lt;/strong&gt; The way a company breaks down their services tells you a lot. Separate components for &lt;code&gt;US-East&lt;/code&gt;, &lt;code&gt;EU-West&lt;/code&gt;, and &lt;code&gt;APAC&lt;/code&gt; confirm multi-region. Separate statuses for &lt;code&gt;API&lt;/code&gt;, &lt;code&gt;WebSockets&lt;/code&gt;, &lt;code&gt;Background Jobs&lt;/code&gt;, and &lt;code&gt;CDN&lt;/code&gt; tell you how they've segmented their infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incident history reveals hidden dependencies.&lt;/strong&gt; When systems fail, companies explain why — and that explanation often names an upstream vendor. This is especially powerful for finding security and infrastructure tools that never show up in DNS or network calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; After the CrowdStrike outage on July 19, 2024, dozens of companies posted status page incidents explicitly mentioning CrowdStrike. No scanner, DNS lookup, or job posting would ever reveal a company uses CrowdStrike EDR. But their own status page did.&lt;/p&gt;

&lt;p&gt;The technique: if a vendor had a major outage on a known date, search status pages for companies that reported issues on the same day mentioning that vendor. You now have a list of confirmed customers.&lt;/p&gt;




&lt;h3&gt;
  
  
  10. Mine historical job postings
&lt;/h3&gt;

&lt;p&gt;When a company hires, they list the exact tools the hire will use. Engineering roles are obvious, but also look at: SRE and DevOps postings (infra stack), data engineering roles (pipeline tools), platform engineering (internal dev platform), and security roles (SIEM, EDR, vulnerability management).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Most companies only have a few active listings, and old ones disappear from LinkedIn and career pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; The &lt;a href="https://web.archive.org" rel="noopener noreferrer"&gt;Wayback Machine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Paste the company's careers page URL (not an individual job listing) into the Wayback Machine and you'll find archived snapshots going back years. Browse old job listings that are no longer live and collect the technologies mentioned.&lt;/p&gt;

&lt;p&gt;Once you've collected 8–10 postings across different roles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Paste all job descriptions into an LLM and ask:
"Extract every specific technology, tool, framework, or platform 
mentioned across these job descriptions, count how many postings 
each appears in, and group them by category."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequency is the signal. If &lt;code&gt;Terraform&lt;/code&gt;, &lt;code&gt;Kubernetes&lt;/code&gt;, and &lt;code&gt;ArgoCD&lt;/code&gt; show up across 6 out of 8 engineering postings, that's the real infra stack. If &lt;code&gt;Jenkins&lt;/code&gt; shows up once in a posting from 2021, they've probably moved on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't only look at engineering jobs.&lt;/strong&gt; A Platform Engineering posting mentioning &lt;code&gt;Backstage&lt;/code&gt; tells you they're building an internal developer platform. An SRE posting mentioning &lt;code&gt;PagerDuty&lt;/code&gt;, &lt;code&gt;Prometheus&lt;/code&gt;, and &lt;code&gt;Grafana&lt;/code&gt; tells you their observability stack. A Data Engineering posting mentioning &lt;code&gt;dbt&lt;/code&gt;, &lt;code&gt;Airflow&lt;/code&gt;, and &lt;code&gt;Snowflake&lt;/code&gt; tells you their data warehouse setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Different techniques reveal different layers of the stack. Here's a practical workflow depending on what you're trying to find:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What cloud/infra do they run?"&lt;/strong&gt;&lt;br&gt;
→ Subdomain enumeration → &lt;code&gt;dig&lt;/code&gt; A records to cloud IP ranges → curl API headers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What does their observability stack look like?"&lt;/strong&gt;&lt;br&gt;
→ Extract third-party domains from network requests → Job postings (SRE/DevOps roles) → DNS TXT records for tools like Datadog, New Relic, Honeycomb&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What's their data/ML infrastructure?"&lt;/strong&gt;&lt;br&gt;
→ GitHub repos (look for Airflow DAGs, dbt models, Spark configs) → Hugging Face org → Job postings for data engineers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What does their auth/security stack look like?"&lt;/strong&gt;&lt;br&gt;
→ DNS TXT records (&lt;code&gt;okta-domain-verification&lt;/code&gt;, &lt;code&gt;onelogin-domain-verification&lt;/code&gt;) → Subprocessor lists → Status page incidents mentioning security vendors&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What CI/CD and dev tools do they use?"&lt;/strong&gt;&lt;br&gt;
→ GitHub Actions workflows in public repos → DNS TXT records (GitHub, Postman, Docker) → Job postings for platform/DevOps roles&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# API header fingerprint&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://api.company.com/

&lt;span class="c"&gt;# DNS TXT records&lt;/span&gt;
dig TXT company.com +short

&lt;span class="c"&gt;# Subdomain enumeration&lt;/span&gt;
subfinder &lt;span class="nt"&gt;-d&lt;/span&gt; company.com &lt;span class="nt"&gt;-silent&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;subdomains.txt

&lt;span class="c"&gt;# Trace subdomain to cloud&lt;/span&gt;
dig +short company.com | xargs &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt; curl &lt;span class="nt"&gt;-s&lt;/span&gt; ipinfo.io/&lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="c"&gt;# Cisco Umbrella search&lt;/span&gt;
curl &lt;span class="nt"&gt;-O&lt;/span&gt; http://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip
unzip top-1m.csv.zip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"company"&lt;/span&gt; top-1m.csv

&lt;span class="c"&gt;# Browser: extract third-party domains&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;...new Set&lt;span class="o"&gt;(&lt;/span&gt;performance.getEntriesByType&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"resource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.map&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;{&lt;/span&gt;try&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="k"&gt;return &lt;/span&gt;new URL&lt;span class="o"&gt;(&lt;/span&gt;r.name&lt;span class="o"&gt;)&lt;/span&gt;.hostname&lt;span class="o"&gt;}&lt;/span&gt;catch&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="k"&gt;return &lt;/span&gt;null&lt;span class="o"&gt;}})&lt;/span&gt;.filter&lt;span class="o"&gt;(&lt;/span&gt;Boolean&lt;span class="o"&gt;))]&lt;/span&gt;.filter&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;!&lt;/span&gt;h.includes&lt;span class="o"&gt;(&lt;/span&gt;location.hostname&lt;span class="o"&gt;))&lt;/span&gt;.sort&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Every technique here is free. The recon tools (Amass, subfinder) are open-source. The DNS lookups are public by design. The Cisco Umbrella list is published daily. GitHub repos and NPM packages are intentionally public.&lt;/p&gt;

&lt;p&gt;I also built an API around these techniques. &lt;a href="https://github.com/HenleyChiu/Bloomberry" rel="noopener noreferrer"&gt;I released it here in Github&lt;/a&gt; if you want to poke around.&lt;/p&gt;

&lt;p&gt;If you're lazy, and looking for free/paid tools that do all or any of the above, I compiled a &lt;a href="https://bloomberry.com/blog/i-tried-6-wappalyzer-alternatives-these-are-the-few-i-liked/" rel="noopener noreferrer"&gt;huge list of tech stack lookup tools&lt;/a&gt; you can use as an alternative to Wappalyzer or Builtwith.&lt;/p&gt;

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