// StackDetect signature set (in-house, MIT). Each entry matches on what ONE GET of the page returns
// (response headers, cookie names, <meta>, <script src>, <link href>, a few inline HTML markers) and, on the
// paid tier, on public DNS records (MX, NS, TXT incl. SPF includes and domain-verification tokens).
// Matchers: string = case-insensitive substring; RegExp = test (capture group 1 = version when present).
// Fields: headers {name: matcher|''}, cookies {name|prefix*: ''}, meta {name: matcher}, scripts [], links [],
// html [] (searched in the first HTML_SCAN_BYTES only), mx [], ns [], txt [], implies [], cats [].
export const CATEGORIES = {
cms: 'CMS', ecommerce: 'Ecommerce', 'site-builder': 'Website builder', blog: 'Blog', 'js-framework': 'JavaScript framework',
'web-framework': 'Web framework', 'static-site-generator': 'Static site generator', language: 'Programming language',
server: 'Web server', cdn: 'CDN', hosting: 'Hosting / PaaS', waf: 'Security / WAF', analytics: 'Analytics', 'tag-manager': 'Tag manager',
advertising: 'Advertising / pixels', marketing: 'Marketing automation', crm: 'CRM', 'live-chat': 'Live chat / support', payments: 'Payments',
'ui-library': 'UI framework / CSS', 'js-library': 'JavaScript library', fonts: 'Fonts', video: 'Video', 'ab-testing': 'A/B testing / personalization',
consent: 'Cookie consent', captcha: 'CAPTCHA / bot protection', monitoring: 'Error tracking / RUM', search: 'Site search', reviews: 'Reviews',
maps: 'Maps', forms: 'Forms / scheduling', 'email-provider': 'Email provider', 'email-delivery': 'Email delivery', 'dns-provider': 'DNS provider',
saas: 'SaaS (verified domain)', 'web3': 'Web3 / wallets', auth: 'Authentication', database: 'Database',
};
export const SIGNATURES = [
// ---- CMS / site builders / ecommerce ----
{ name: 'WordPress', cats: ['cms', 'blog'], meta: { generator: /WordPress\s*([\d.]+)?/i }, scripts: [/\/wp-(?:content|includes)\//i], links: [/\/wp-(?:content|includes)\//i, /\/wp-json\//i], headers: { link: /wp-json|api\.w\.org/i }, implies: ['PHP', 'MySQL'] },
{ name: 'WooCommerce', cats: ['ecommerce'], scripts: [/\/woocommerce\/assets\//i], links: [/\/woocommerce\//i], meta: { generator: /WooCommerce\s*([\d.]+)?/i }, html: [/woocommerce-(?:no-js|page|cart)/i], implies: ['WordPress'] },
{ name: 'Elementor', cats: ['site-builder'], scripts: [/\/elementor(?:-pro)?\/assets\//i], links: [/\/elementor(?:-pro)?\/assets\//i], meta: { generator: /Elementor\s*([\d.]+)?/i }, implies: ['WordPress'] },
{ name: 'Divi', cats: ['site-builder'], scripts: [/\/themes\/Divi\//i, /et-divi/i], links: [/\/themes\/Divi\//i], implies: ['WordPress'] },
{ name: 'Yoast SEO', cats: ['marketing'], html: [/<!-- This site is optimized with the Yoast SEO/i, 'yoast-schema-graph'], implies: ['WordPress'] },
{ name: 'Shopify', cats: ['ecommerce'], headers: { 'x-shopid': '', 'x-shopify-stage': '', 'powered-by': /shopify/i }, scripts: ['cdn.shopify.com', '/cdn/shop/'], links: ['cdn.shopify.com'], html: ['Shopify.theme', 'window.Shopify'], cookies: { _shopify_y: '', _shopify_s: '' } },
{ name: 'Wix', cats: ['site-builder'], headers: { 'x-wix-request-id': '', 'x-wix-renderer-server': '' }, meta: { generator: /Wix\.com/i }, scripts: ['static.parastorage.com', 'static.wixstatic.com'], links: ['static.wixstatic.com', 'static.parastorage.com'] },
{ name: 'Squarespace', cats: ['site-builder'], headers: { server: /Squarespace/i }, scripts: ['static1.squarespace.com', 'assets.squarespace.com'], links: ['static1.squarespace.com'], html: ['Static.SQUARESPACE_CONTEXT'] },
{ name: 'Webflow', cats: ['site-builder'], meta: { generator: /Webflow/i }, html: [/data-wf-(?:page|site)=/i], scripts: [/(?:website-files|webflow)\.com\/.*webflow/i, 'assets.website-files.com', 'cdn.prod.website-files.com'], links: ['assets.website-files.com', 'cdn.prod.website-files.com'] },
{ name: 'Framer', cats: ['site-builder'], meta: { generator: /Framer\s*([\w.]+)?/i }, scripts: ['framerusercontent.com', 'events.framer.com'], headers: { server: /^Framer/i } },
{ name: 'Ghost', cats: ['cms', 'blog'], meta: { generator: /Ghost\s*([\d.]+)?/i }, headers: { 'x-ghost-cache-status': '' }, scripts: [/\/ghost\/api\//i, 'cdn.jsdelivr.net/ghost/'] },
{ name: 'Drupal', cats: ['cms'], meta: { generator: /Drupal\s*([\d.]+)?/i }, headers: { 'x-drupal-cache': '', 'x-generator': /Drupal\s*([\d.]+)?/i, 'x-drupal-dynamic-cache': '' }, scripts: [/\/sites\/(?:all|default)\/(?:modules|themes|files)\//i, /\/core\/misc\/drupal\.js/i], html: ['drupal-settings-json'], implies: ['PHP'] },
{ name: 'Joomla', cats: ['cms'], meta: { generator: /Joomla!?\s*([\d.]+)?/i }, scripts: [/\/media\/(?:jui|system)\/js\//i], implies: ['PHP'] },
{ name: 'HubSpot CMS', cats: ['cms'], headers: { 'x-hs-hub-id': '', 'x-hs-cache-config': '' }, meta: { generator: /HubSpot/i }, scripts: ['/hs/hsstatic/', 'static.hsappstatic.net'] },
{ name: 'Magento', cats: ['ecommerce'], headers: { 'x-magento-cache-debug': '', 'x-magento-tags': '' }, scripts: [/\/static\/(?:version\d+\/)?frontend\/Magento/i, 'mage/cookies'], html: ['Magento_PageCache', /data-mage-init/i], cookies: { 'mage-cache-storage': '', 'mage-cache-sessid': '' }, implies: ['PHP'] },
{ name: 'BigCommerce', cats: ['ecommerce'], scripts: ['cdn11.bigcommerce.com', 'bigcommerce.com/s-'], html: ['BCData'], headers: { 'x-bc-storefront-version': '' } },
{ name: 'PrestaShop', cats: ['ecommerce'], meta: { generator: /PrestaShop/i }, html: [/var prestashop\s*=/i], cookies: { 'PrestaShop-*': '' }, implies: ['PHP'] },
{ name: 'Salesforce Commerce Cloud', cats: ['ecommerce'], scripts: ['demandware.static', '/on/demandware.store/'], links: ['demandware.static'], cookies: { dwsid: '', dwanonymous_: '' } },
{ name: 'Ecwid', cats: ['ecommerce'], scripts: ['app.ecwid.com/script.js'] },
{ name: 'Gumroad', cats: ['ecommerce'], scripts: ['gumroad.com/js/gumroad.js'] },
{ name: 'Substack', cats: ['blog'], scripts: ['substackcdn.com'], links: ['substackcdn.com'] },
{ name: 'Medium', cats: ['blog'], scripts: ['cdn-client.medium.com'], links: ['cdn-client.medium.com'] },
{ name: 'Blogger', cats: ['blog'], meta: { generator: /^blogger$/i }, scripts: ['www.blogger.com/static'] },
{ name: 'Tilda', cats: ['site-builder'], scripts: ['static.tildacdn.com'], links: ['static.tildacdn.com'] },
{ name: 'Weebly', cats: ['site-builder'], scripts: ['editmysite.com'], links: ['editmysite.com'] },
{ name: 'GoDaddy Website Builder', cats: ['site-builder'], meta: { generator: /Starfield Technologies|GoDaddy Website Builder/i }, scripts: ['img1.wsimg.com'] },
{ name: 'Contentful', cats: ['cms'], scripts: ['ctfassets.net'], links: ['images.ctfassets.net'], html: ['images.ctfassets.net'] },
{ name: 'Sanity', cats: ['cms'], html: ['cdn.sanity.io'], links: ['cdn.sanity.io'] },
{ name: 'Strapi', cats: ['cms'], headers: { 'x-powered-by': /Strapi/i } },
{ name: 'Mintlify', cats: ['cms'], scripts: ['mintlify'], links: ['mintlify'], meta: { generator: /Mintlify/i } },
{ name: 'GitBook', cats: ['cms'], scripts: ['gitbook.com', 'gitbook-'], meta: { generator: /GitBook\s*([\d.]+)?/i } },
{ name: 'Notion', cats: ['site-builder'], html: ['notion-app-inner', /"notion-[a-z-]+"/], scripts: [/notion\.(?:so|site)\//i] },
{ name: 'Docusaurus', cats: ['static-site-generator'], meta: { generator: /Docusaurus\s*v?([\d.]+)?/i }, implies: ['React'] },
{ name: 'Hugo', cats: ['static-site-generator'], meta: { generator: /Hugo\s*([\d.]+)?/i } },
{ name: 'Jekyll', cats: ['static-site-generator'], meta: { generator: /Jekyll\s*v?([\d.]+)?/i } },
{ name: 'Hexo', cats: ['static-site-generator'], meta: { generator: /Hexo\s*([\d.]+)?/i } },
{ name: 'Eleventy', cats: ['static-site-generator'], meta: { generator: /Eleventy\s*v?([\d.]+)?/i } },
{ name: 'VitePress', cats: ['static-site-generator'], meta: { generator: /VitePress\s*v?([\d.]+)?/i }, implies: ['Vue.js'] },
{ name: 'MkDocs', cats: ['static-site-generator'], meta: { generator: /mkdocs-?([\d.]+)?/i } },
{ name: 'Astro', cats: ['js-framework', 'static-site-generator'], meta: { generator: /Astro\s*v?([\d.]+)?/i }, html: [/<astro-island/i], scripts: [/\/_astro\//] , links: [/\/_astro\//] },
// ---- JS frameworks / libraries ----
{ name: 'Next.js', cats: ['js-framework'], headers: { 'x-powered-by': /Next\.js\s*([\d.]+)?/i, 'x-nextjs-cache': '', 'x-nextjs-prerender': '', 'x-nextjs-stale-time': '' }, scripts: ['/_next/static/'], links: ['/_next/static/'], html: ['__NEXT_DATA__', 'self.__next_f'], implies: ['React', 'Node.js'] },
{ name: 'Nuxt', cats: ['js-framework'], scripts: ['/_nuxt/'], links: ['/_nuxt/'], html: ['window.__NUXT__', /<div id="__nuxt"/], implies: ['Vue.js', 'Node.js'] },
{ name: 'Gatsby', cats: ['js-framework', 'static-site-generator'], meta: { generator: /Gatsby\s*([\d.]+)?/i }, html: ['id="___gatsby"'], implies: ['React'] },
{ name: 'Remix', cats: ['js-framework'], html: ['window.__remixContext', '__remixManifest'], implies: ['React'] },
{ name: 'SvelteKit', cats: ['js-framework'], scripts: ['/_app/immutable/'], links: ['/_app/immutable/'], html: ['__sveltekit_', /data-sveltekit-/], implies: ['Svelte'] },
{ name: 'Svelte', cats: ['js-framework'], html: [/class="[^"]*\bsvelte-[a-z0-9]{5,}/] },
{ name: 'Angular', cats: ['js-framework'], html: [/\bng-version="([\d.]+)"/, /<[a-z-]+ _nghost-/] },
{ name: 'React', cats: ['js-framework'], html: [/data-reactroot/i, 'react-dom'], scripts: [/react(?:-dom)?(?:\.production)?(?:\.min)?\.js/i, /\/react@([\d.]+)/] },
{ name: 'Vue.js', cats: ['js-framework'], html: [/\bdata-v-[0-9a-f]{8}\b/, /data-server-rendered="true"/], scripts: [/\/vue(?:\.global|\.runtime)?(?:\.prod)?(?:\.min)?\.js/i, /\/vue@([\d.]+)/] },
{ name: 'Ember.js', cats: ['js-framework'], html: [/<meta name="[^"]+\/config\/environment"/] , scripts: [/ember(?:\.min)?\.js/i] },
{ name: 'Alpine.js', cats: ['js-library'], scripts: [/alpinejs@?([\d.]+)?/i, /alpine(?:\.min)?\.js/i], html: [/\bx-data="/] },
{ name: 'htmx', cats: ['js-library'], scripts: [/htmx(?:\.org)?@?([\d.]+)?(?:\/dist)?\/htmx(?:\.min)?\.js|\/htmx(?:\.min)?\.js/i], html: [/\bhx-(?:get|post|target|swap)="/] },
{ name: 'jQuery', cats: ['js-library'], scripts: [/jquery[-.]?([\d]+\.[\d.]+)?(?:\.slim)?(?:\.min)?\.js/i, /\/jquery@([\d.]+)/i, /\/jquery\/([\d.]+)\//i] },
{ name: 'jQuery UI', cats: ['js-library'], scripts: [/jquery-ui(?:\.min)?\.js|\/jqueryui\/([\d.]+)\//i], implies: ['jQuery'] },
{ name: 'Lodash', cats: ['js-library'], scripts: [/lodash(?:\.min)?\.js|\/lodash@([\d.]+)/i] },
{ name: 'GSAP', cats: ['js-library'], scripts: [/gsap(?:\.min)?\.js|\/gsap@([\d.]+)|\/gsap\/([\d.]+)\//i] },
{ name: 'Three.js', cats: ['js-library'], scripts: [/three(?:\.module)?(?:\.min)?\.js|\/three@([\d.]+)/i] },
{ name: 'core-js', cats: ['js-library'], scripts: [/core-js(?:-bundle)?@?([\d.]+)?/i] },
{ name: 'Turbo', cats: ['js-library'], html: [/<turbo-frame/i, 'data-turbo-track'] },
{ name: 'Stimulus', cats: ['js-library'], html: [/\bdata-controller="/] },
{ name: 'Livewire', cats: ['js-library'], html: [/\bwire:(?:id|model|click)=/], scripts: ['livewire.js', '/livewire/'], implies: ['Laravel'] },
{ name: 'Inertia.js', cats: ['js-library'], html: [/data-page="\{"component/] },
{ name: 'Vite', cats: ['js-library'], scripts: ['/@vite/client', /\/assets\/index-[\w-]{8}\.js/], html: ['/@vite/client'] },
{ name: 'webpack', cats: ['js-library'], html: ['webpackChunk', 'webpackJsonp'] },
// ---- UI / CSS / fonts ----
{ name: 'Bootstrap', cats: ['ui-library'], links: [/bootstrap(?:\.min)?\.css|\/bootstrap@([\d.]+)|\/bootstrap\/([\d.]+)\//i], scripts: [/bootstrap(?:\.bundle)?(?:\.min)?\.js|\/bootstrap@([\d.]+)/i] },
{ name: 'Tailwind CSS', cats: ['ui-library'], scripts: ['cdn.tailwindcss.com', /\/tailwindcss@([\d.]+)/], links: [/tailwind(?:css)?(?:@([\d.]+))?[^"']*\.css/i], html: [/\bclass="[^"]*\b(?:flex|grid) [^"]*\b(?:px|py|mx|my|gap)-\d[^"]*\b(?:sm|md|lg):[a-z]/, '--tw-'] },
{ name: 'Bulma', cats: ['ui-library'], links: [/bulma(?:\.min)?\.css|\/bulma@([\d.]+)/i] },
{ name: 'Foundation', cats: ['ui-library'], links: [/foundation(?:\.min)?\.css/i], scripts: [/foundation(?:\.min)?\.js/i] },
{ name: 'Material UI', cats: ['ui-library'], html: [/class="[^"]*\bMui[A-Z][a-zA-Z]+-root/] , implies: ['React'] },
{ name: 'Chakra UI', cats: ['ui-library'], html: [/class="[^"]*\bchakra-/] , implies: ['React'] },
{ name: 'Font Awesome', cats: ['fonts'], links: [/font-?awesome|\/fontawesome-free@([\d.]+)|use\.fontawesome\.com|kit\.fontawesome\.com/i], scripts: [/kit\.fontawesome\.com|font-?awesome/i] },
{ name: 'Google Fonts', cats: ['fonts'], links: ['fonts.googleapis.com', 'fonts.gstatic.com'] },
{ name: 'Adobe Fonts', cats: ['fonts'], links: ['use.typekit.net', 'p.typekit.net'], scripts: ['use.typekit.net'] },
{ name: 'Bunny Fonts', cats: ['fonts'], links: ['fonts.bunny.net'] },
// ---- servers / languages / backend frameworks ----
{ name: 'Nginx', cats: ['server'], headers: { server: /nginx(?:\/([\d.]+))?/i } },
{ name: 'Apache HTTP Server', cats: ['server'], headers: { server: /Apache(?:\/([\d.]+))?(?! ?Tomcat|-Coyote)/i } },
{ name: 'Microsoft IIS', cats: ['server'], headers: { server: /Microsoft-IIS(?:\/([\d.]+))?/i }, implies: ['Microsoft ASP.NET'] },
{ name: 'LiteSpeed', cats: ['server'], headers: { server: /LiteSpeed/i, 'x-litespeed-cache': '' } },
{ name: 'OpenResty', cats: ['server'], headers: { server: /openresty(?:\/([\d.]+))?/i }, implies: ['Nginx'] },
{ name: 'Caddy', cats: ['server'], headers: { server: /^Caddy/i } },
{ name: 'Envoy', cats: ['server'], headers: { server: /^envoy/i, 'x-envoy-upstream-service-time': '' } },
{ name: 'Apache Tomcat', cats: ['server'], headers: { server: /Apache-Coyote|Tomcat/i }, implies: ['Java'] },
{ name: 'Gunicorn', cats: ['server'], headers: { server: /gunicorn(?:\/([\d.]+))?/i }, implies: ['Python'] },
{ name: 'Uvicorn', cats: ['server'], headers: { server: /uvicorn/i }, implies: ['Python'] },
{ name: 'Kestrel', cats: ['server'], headers: { server: /^Kestrel/i }, implies: ['Microsoft ASP.NET'] },
{ name: 'PHP', cats: ['language'], headers: { 'x-powered-by': /PHP(?:\/([\d.]+))?/i }, cookies: { PHPSESSID: '' } },
{ name: 'Microsoft ASP.NET', cats: ['web-framework'], headers: { 'x-aspnet-version': /([\d.]+)/, 'x-powered-by': /ASP\.NET/i, 'x-aspnetmvc-version': '' }, cookies: { 'ASP.NET_SessionId': '', '.AspNetCore.*': '' }, html: ['__VIEWSTATE'] },
{ name: 'Express', cats: ['web-framework'], headers: { 'x-powered-by': /^Express$/i }, implies: ['Node.js'] },
{ name: 'Node.js', cats: ['language'] },
{ name: 'Python', cats: ['language'] },
{ name: 'Java', cats: ['language'], cookies: { JSESSIONID: '' } },
{ name: 'Ruby', cats: ['language'] },
{ name: 'MySQL', cats: ['database'] },
{ name: 'Ruby on Rails', cats: ['web-framework'], headers: { 'x-powered-by': /Phusion Passenger|Rails/i, 'x-runtime': /^\d+\.\d+$/ }, meta: { 'csrf-param': /authenticity_token/ }, cookies: { '_*_session': '' }, implies: ['Ruby'] },
{ name: 'Laravel', cats: ['web-framework'], cookies: { laravel_session: '', 'XSRF-TOKEN': '' }, implies: ['PHP'] },
{ name: 'Django', cats: ['web-framework'], cookies: { csrftoken: '', django_language: '' }, html: ['csrfmiddlewaretoken'], implies: ['Python'] },
{ name: 'Flask', cats: ['web-framework'], headers: { server: /Werkzeug(?:\/([\d.]+))?/i }, implies: ['Python'] },
{ name: 'Phoenix', cats: ['web-framework'], html: [/data-phx-(?:main|session|view)/] },
{ name: 'Spring', cats: ['web-framework'], headers: { 'x-application-context': '' }, implies: ['Java'] },
// ---- CDN / hosting / security ----
{ name: 'Cloudflare', cats: ['cdn', 'waf'], headers: { server: /^cloudflare$/i, 'cf-ray': '', 'cf-cache-status': '' }, cookies: { __cf_bm: '', __cflb: '', _cfuvid: '' }, ns: ['ns.cloudflare.com'], scripts: ['cdnjs.cloudflare.com', 'static.cloudflareinsights.com'] },
{ name: 'Cloudflare Pages', cats: ['hosting'], headers: { 'cf-pages': '' }, implies: ['Cloudflare'] },
{ name: 'Cloudflare Web Analytics', cats: ['analytics'], scripts: ['static.cloudflareinsights.com/beacon'], implies: ['Cloudflare'] },
{ name: 'Cloudflare Turnstile', cats: ['captcha'], scripts: ['challenges.cloudflare.com/turnstile'] },
{ name: 'Amazon CloudFront', cats: ['cdn'], headers: { 'x-amz-cf-id': '', 'x-amz-cf-pop': '', via: /CloudFront/i } },
{ name: 'Amazon S3', cats: ['hosting'], headers: { server: /^AmazonS3$/i, 'x-amz-request-id': '' } },
{ name: 'Amazon Web Services', cats: ['hosting'], headers: { 'x-amzn-requestid': '', 'x-amzn-trace-id': '' }, ns: ['awsdns-'] },
{ name: 'Fastly', cats: ['cdn'], headers: { 'x-served-by': /cache-[a-z]{3}/i, 'fastly-debug-digest': '', 'x-fastly-request-id': '' } },
{ name: 'Akamai', cats: ['cdn'], headers: { 'x-akamai-transformed': '', 'akamai-grn': '', server: /AkamaiGHost|AkamaiNetStorage/i }, ns: ['akam.net'] },
{ name: 'Vercel', cats: ['hosting'], headers: { server: /^Vercel$/i, 'x-vercel-id': '', 'x-vercel-cache': '' }, ns: ['vercel-dns.com'] },
{ name: 'Netlify', cats: ['hosting'], headers: { server: /^Netlify$/i, 'x-nf-request-id': '' } },
{ name: 'GitHub Pages', cats: ['hosting'], headers: { server: /^GitHub\.com$/i }, excludeHosts: ['github.com'] },
{ name: 'Heroku', cats: ['hosting'], headers: { via: /vegur/i }, implies: [] },
{ name: 'Render', cats: ['hosting'], headers: { 'x-render-origin-server': '', 'rndr-id': '' } },
{ name: 'Fly.io', cats: ['hosting'], headers: { 'fly-request-id': '', server: /^Fly\//i } },
{ name: 'Railway', cats: ['hosting'], headers: { 'x-railway-request-id': '', 'x-railway-edge': '' } },
{ name: 'Google Cloud', cats: ['hosting'], headers: { via: /1\.1 google/i, server: /^Google Frontend$/i }, ns: ['googledomains.com', 'ns-cloud-'] },
{ name: 'Firebase Hosting', cats: ['hosting'], headers: { 'x-firebase-hosting': '' }, scripts: [/\/__\/firebase\//] },
{ name: 'Microsoft Azure', cats: ['hosting'], headers: { 'x-azure-ref': '', 'x-ms-request-id': '' }, ns: ['azure-dns.'] },
{ name: 'Kinsta', cats: ['hosting'], headers: { 'x-kinsta-cache': '' } },
{ name: 'WP Engine', cats: ['hosting'], headers: { 'x-powered-by': /WP Engine/i, wpe: '' } },
{ name: 'Pantheon', cats: ['hosting'], headers: { 'x-pantheon-styx-hostname': '' } },
{ name: 'Sucuri', cats: ['waf'], headers: { 'x-sucuri-id': '', server: /Sucuri/i } },
{ name: 'Imperva', cats: ['waf'], headers: { 'x-iinfo': '', 'x-cdn': /Imperva|Incapsula/i }, cookies: { 'incap_ses_*': '', 'visid_incap_*': '' } },
{ name: 'DataDome', cats: ['captcha'], headers: { 'x-datadome': '' }, cookies: { datadome: '' }, scripts: ['js.datadome.co'] },
{ name: 'PerimeterX', cats: ['captcha'], cookies: { _px3: '', _pxvid: '' }, scripts: ['client.perimeterx.net', /\/px\/client\/main\.min\.js/] },
{ name: 'reCAPTCHA', cats: ['captcha'], scripts: ['www.google.com/recaptcha', 'www.gstatic.com/recaptcha', 'recaptcha.net/recaptcha'], html: ['g-recaptcha'] },
{ name: 'hCaptcha', cats: ['captcha'], scripts: ['hcaptcha.com/1/api.js', 'js.hcaptcha.com'], html: ['h-captcha'] },
{ name: 'jsDelivr', cats: ['cdn'], scripts: ['cdn.jsdelivr.net'], links: ['cdn.jsdelivr.net'] },
{ name: 'unpkg', cats: ['cdn'], scripts: ['unpkg.com/'], links: ['unpkg.com/'] },
{ name: 'cdnjs', cats: ['cdn'], scripts: ['cdnjs.cloudflare.com'], links: ['cdnjs.cloudflare.com'] },
// ---- analytics / tags / ads / marketing ----
{ name: 'Google Analytics', cats: ['analytics'], scripts: [/google-analytics\.com\/(?:analytics|ga)\.js/, /googletagmanager\.com\/gtag\/js\?id=(?:G|UA)-/], html: [/gtag\(\s*['"]config['"]\s*,\s*['"](?:G|UA)-/], cookies: { _ga: '', '_ga_*': '' } },
{ name: 'Google Tag Manager', cats: ['tag-manager'], scripts: [/googletagmanager\.com\/gtm\.js/], html: [/googletagmanager\.com\/(?:gtm\.js|ns\.html)\?id=GTM-/, /['"]GTM-[A-Z0-9]{4,}['"]/] },
{ name: 'Google Ads', cats: ['advertising'], scripts: ['googleadservices.com', /googletagmanager\.com\/gtag\/js\?id=AW-/], html: [/['"]AW-\d{6,}['"]/] },
{ name: 'Google AdSense', cats: ['advertising'], scripts: ['pagead2.googlesyndication.com/pagead/js/adsbygoogle'] },
{ name: 'Google Maps', cats: ['maps'], scripts: ['maps.googleapis.com/maps/api/js'], html: ['google.com/maps/embed'] },
{ name: 'Meta Pixel', cats: ['advertising'], scripts: ['connect.facebook.net/en_US/fbevents.js', /connect\.facebook\.net\/[a-z_A-Z]+\/fbevents\.js/], html: [/fbq\(\s*['"]init['"]/] },
{ name: 'LinkedIn Insight Tag', cats: ['advertising'], scripts: ['snap.licdn.com/li.lms-analytics'], html: ['_linkedin_partner_id'] },
{ name: 'TikTok Pixel', cats: ['advertising'], scripts: ['analytics.tiktok.com'], html: ['ttq.load('] },
{ name: 'X (Twitter) Pixel', cats: ['advertising'], scripts: ['static.ads-twitter.com/uwt.js'] },
{ name: 'Microsoft Advertising', cats: ['advertising'], scripts: ['bat.bing.com/bat.js'] },
{ name: 'Pinterest Tag', cats: ['advertising'], scripts: ['s.pinimg.com/ct/core.js'] },
{ name: 'Reddit Pixel', cats: ['advertising'], scripts: ['www.redditstatic.com/ads/pixel.js'] },
{ name: 'Segment', cats: ['analytics'], scripts: ['cdn.segment.com/analytics.js', 'cdn.segment.io'] },
{ name: 'Mixpanel', cats: ['analytics'], scripts: ['cdn.mxpnl.com', 'mixpanel'] },
{ name: 'Amplitude', cats: ['analytics'], scripts: ['cdn.amplitude.com', 'amplitude.com/libs'] },
{ name: 'Heap', cats: ['analytics'], scripts: ['cdn.heapanalytics.com'] },
{ name: 'PostHog', cats: ['analytics'], scripts: [/(?:us|eu)(?:-assets)?\.i\.posthog\.com|posthog/i] },
{ name: 'Plausible', cats: ['analytics'], scripts: ['plausible.io/js/'] },
{ name: 'Fathom', cats: ['analytics'], scripts: ['cdn.usefathom.com'] },
{ name: 'Matomo', cats: ['analytics'], scripts: [/matomo(?:\.cloud)?[^"']*\.js|piwik\.js/i], html: ['_paq.push'] },
{ name: 'Umami', cats: ['analytics'], scripts: [/umami(?:\.is)?[^"']*\/script\.js|analytics\.umami\.is/i], html: ['data-website-id'] },
{ name: 'Vercel Analytics', cats: ['analytics'], scripts: ['/_vercel/insights/script.js', 'va.vercel-scripts.com'], implies: ['Vercel'] },
{ name: 'Hotjar', cats: ['analytics'], scripts: ['static.hotjar.com'], html: ['_hjSettings'] },
{ name: 'Microsoft Clarity', cats: ['analytics'], scripts: ['www.clarity.ms/tag'], html: [/clarity\.ms\/tag\//] },
{ name: 'FullStory', cats: ['analytics'], scripts: ['edge.fullstory.com', 'fullstory.com/s/fs.js'] },
{ name: 'Yandex Metrica', cats: ['analytics'], scripts: ['mc.yandex.ru/metrika'] },
{ name: 'HubSpot', cats: ['marketing', 'crm'], scripts: ['js.hs-scripts.com', 'js.hs-analytics.net', 'js.hsforms.net', 'js.hscollectedforms.net'], cookies: { hubspotutk: '', __hstc: '' } },
{ name: 'Marketo', cats: ['marketing'], scripts: ['munchkin.marketo.net', /\/js\/forms2\/js\/forms2(?:\.min)?\.js/] },
{ name: 'Pardot', cats: ['marketing'], scripts: ['pi.pardot.com', 'cdn.pardot.com'] },
{ name: 'Mailchimp', cats: ['marketing'], scripts: ['chimpstatic.com', 'list-manage.com'], html: ['list-manage.com/subscribe'] },
{ name: 'Klaviyo', cats: ['marketing'], scripts: ['static.klaviyo.com', 'a.klaviyo.com'] },
{ name: 'ConvertKit', cats: ['marketing'], scripts: ['f.convertkit.com'] },
{ name: 'Salesforce', cats: ['crm'], scripts: ['force.com/', 'salesforceliveagent.com'] },
{ name: 'Optimizely', cats: ['ab-testing'], scripts: ['cdn.optimizely.com'] },
{ name: 'VWO', cats: ['ab-testing'], scripts: ['dev.visualwebsiteoptimizer.com'], html: ['_vwo_code'] },
{ name: 'LaunchDarkly', cats: ['ab-testing'], scripts: ['launchdarkly'] },
// ---- support / chat / forms / payments / misc ----
{ name: 'Intercom', cats: ['live-chat'], scripts: ['widget.intercom.io', 'js.intercomcdn.com'], html: ['intercomSettings'] },
{ name: 'Zendesk', cats: ['live-chat'], scripts: ['static.zdassets.com', 'ekr.zdassets.com'] },
{ name: 'Drift', cats: ['live-chat'], scripts: ['js.driftt.com'] },
{ name: 'Crisp', cats: ['live-chat'], scripts: ['client.crisp.chat'] },
{ name: 'Tawk.to', cats: ['live-chat'], scripts: ['embed.tawk.to'] },
{ name: 'LiveChat', cats: ['live-chat'], scripts: ['cdn.livechatinc.com'] },
{ name: 'Freshchat', cats: ['live-chat'], scripts: ['wchat.freshchat.com', 'freshworks.com/'] },
{ name: 'Tidio', cats: ['live-chat'], scripts: ['code.tidio.co'] },
{ name: 'Calendly', cats: ['forms'], scripts: ['assets.calendly.com'], html: ['calendly.com/'] },
{ name: 'Typeform', cats: ['forms'], scripts: ['embed.typeform.com'], html: ['form.typeform.com'] },
{ name: 'Tally', cats: ['forms'], scripts: ['tally.so/widgets'] },
{ name: 'Stripe', cats: ['payments'], scripts: ['js.stripe.com'], html: ['buy.stripe.com', 'checkout.stripe.com'] },
{ name: 'PayPal', cats: ['payments'], scripts: ['www.paypal.com/sdk/js', 'paypalobjects.com'] },
{ name: 'Paddle', cats: ['payments'], scripts: ['cdn.paddle.com'] },
{ name: 'Lemon Squeezy', cats: ['payments'], scripts: ['app.lemonsqueezy.com/js/lemon.js'], html: ['lemonsqueezy.com/checkout'] },
{ name: 'Klarna', cats: ['payments'], scripts: ['klarnaservices.com', 'klarna.com/'] },
{ name: 'Coinbase Commerce', cats: ['payments', 'web3'], scripts: ['commerce.coinbase.com'] },
{ name: 'WalletConnect', cats: ['web3'], scripts: ['walletconnect'], html: ['walletconnect'] },
{ name: 'Ethers.js', cats: ['web3'], scripts: [/ethers(?:\.umd)?(?:\.min)?\.js|\/ethers@([\d.]+)/i] },
{ name: 'Auth0', cats: ['auth'], scripts: ['cdn.auth0.com'] },
{ name: 'Clerk', cats: ['auth'], scripts: [/clerk(?:\.browser)?(?:\.js)?|clerk\.accounts\.dev/i] },
{ name: 'Supabase', cats: ['auth'], html: ['.supabase.co/'] },
{ name: 'Sentry', cats: ['monitoring'], scripts: ['browser.sentry-cdn.com', 'js.sentry-cdn.com'], html: [/ingest(?:\.[a-z]+)?\.sentry\.io/] },
{ name: 'Datadog RUM', cats: ['monitoring'], scripts: ['datadoghq-browser-agent.com'] },
{ name: 'New Relic', cats: ['monitoring'], scripts: ['js-agent.newrelic.com'], html: ['NREUM'] },
{ name: 'Bugsnag', cats: ['monitoring'], scripts: ['d2wy8f7a9ursnm.cloudfront.net', 'bugsnag'] },
{ name: 'Algolia', cats: ['search'], scripts: ['algolia', 'algoliasearch'], html: ['-dsn.algolia.net'] },
{ name: 'OneTrust', cats: ['consent'], scripts: ['cdn.cookielaw.org', 'optanon'], cookies: { OptanonConsent: '' } },
{ name: 'Cookiebot', cats: ['consent'], scripts: ['consent.cookiebot.com'] },
{ name: 'Osano', cats: ['consent'], scripts: ['cmp.osano.com'] },
{ name: 'Termly', cats: ['consent'], scripts: ['app.termly.io'] },
{ name: 'Iubenda', cats: ['consent'], scripts: ['cdn.iubenda.com'] },
{ name: 'Trustpilot', cats: ['reviews'], scripts: ['widget.trustpilot.com'] },
{ name: 'YouTube', cats: ['video'], html: [/youtube(?:-nocookie)?\.com\/embed\//] },
{ name: 'Vimeo', cats: ['video'], scripts: ['player.vimeo.com'], html: ['player.vimeo.com/video'] },
{ name: 'Wistia', cats: ['video'], scripts: ['fast.wistia.com', 'fast.wistia.net'] },
{ name: 'Mux', cats: ['video'], scripts: ['mux.com', 'mux-player'], html: ['stream.mux.com'] },
{ name: 'Open Graph', cats: ['marketing'], meta: { 'og:title': '' } },
{ name: 'Twitter Cards', cats: ['marketing'], meta: { 'twitter:card': '' } },
// ---- DNS-only (paid tier): email provider, email delivery, DNS host ----
{ name: 'Google Workspace', cats: ['email-provider'], mx: ['aspmx.l.google.com', 'googlemail.com', 'smtp.google.com'], txt: ['_spf.google.com'] },
{ name: 'Microsoft 365', cats: ['email-provider'], mx: ['mail.protection.outlook.com'], txt: ['spf.protection.outlook.com', /^MS=ms\d+/] },
{ name: 'Zoho Mail', cats: ['email-provider'], mx: ['zoho.com', 'zoho.eu'], txt: ['zoho.com', 'zoho-verification='] },
{ name: 'Proton Mail', cats: ['email-provider'], mx: ['protonmail.ch'], txt: ['protonmail-verification='] },
{ name: 'Fastmail', cats: ['email-provider'], mx: ['messagingengine.com'] },
{ name: 'iCloud Mail', cats: ['email-provider'], mx: ['mail.icloud.com'], txt: ['apple-domain='] },
{ name: 'Yahoo Mail', cats: ['email-provider'], mx: ['yahoodns.net'] },
{ name: 'Mimecast', cats: ['email-provider'], mx: ['mimecast.com'] },
{ name: 'Proofpoint', cats: ['email-provider'], mx: ['pphosted.com', 'ppe-hosted.com'] },
{ name: 'Barracuda', cats: ['email-provider'], mx: ['barracudanetworks.com'] },
{ name: 'Amazon SES', cats: ['email-delivery'], mx: ['amazonses.com'], txt: ['amazonses.com'] },
{ name: 'SendGrid', cats: ['email-delivery'], txt: ['sendgrid.net'] },
{ name: 'Mailgun', cats: ['email-delivery'], mx: ['mailgun.org'], txt: ['mailgun.org'] },
{ name: 'Postmark', cats: ['email-delivery'], txt: ['spf.mtasv.net'] },
{ name: 'Mailjet', cats: ['email-delivery'], txt: ['spf.mailjet.com'] },
{ name: 'SparkPost', cats: ['email-delivery'], txt: ['sparkpostmail.com'] },
{ name: 'Mandrill', cats: ['email-delivery'], txt: ['spf.mandrillapp.com'] },
{ name: 'Brevo', cats: ['email-delivery'], txt: ['sendinblue.com', 'brevo-code:', 'spf.brevo.com'] },
{ name: 'Mailchimp (sending)', cats: ['email-delivery'], txt: ['servers.mcsv.net'] },
{ name: 'Zendesk (email)', cats: ['email-delivery'], txt: ['mail.zendesk.com'] },
{ name: 'Salesforce (email)', cats: ['email-delivery'], txt: ['_spf.salesforce.com'] },
{ name: 'HubSpot (email)', cats: ['email-delivery'], txt: [/\.hubspotemail\.net|spf\.hubspot/] },
{ name: 'Freshdesk (email)', cats: ['email-delivery'], txt: ['email.freshdesk.com'] },
{ name: 'Cloudflare DNS', cats: ['dns-provider'], ns: ['ns.cloudflare.com'] },
{ name: 'Amazon Route 53', cats: ['dns-provider'], ns: ['awsdns-'] },
{ name: 'Google Cloud DNS', cats: ['dns-provider'], ns: ['googledomains.com', /ns-cloud-[a-e]\d\.google/] },
{ name: 'Azure DNS', cats: ['dns-provider'], ns: ['azure-dns.'] },
{ name: 'GoDaddy DNS', cats: ['dns-provider'], ns: ['domaincontrol.com'] },
{ name: 'Namecheap DNS', cats: ['dns-provider'], ns: ['registrar-servers.com'] },
{ name: 'DigitalOcean DNS', cats: ['dns-provider'], ns: ['digitalocean.com'] },
{ name: 'NS1', cats: ['dns-provider'], ns: ['nsone.net'] },
{ name: 'Vercel DNS', cats: ['dns-provider'], ns: ['vercel-dns.com'] },
{ name: 'Squarespace Domains', cats: ['dns-provider'], ns: ['squarespacedns.com'] },
{ name: 'Hostinger DNS', cats: ['dns-provider'], ns: ['dns-parking.com'] },
// ---- SaaS seen through TXT domain-verification tokens (paid tier) ----
{ name: 'Google Search Console', cats: ['saas'], txt: ['google-site-verification='] },
{ name: 'Facebook Business', cats: ['saas'], txt: ['facebook-domain-verification='] },
{ name: 'Atlassian', cats: ['saas'], txt: ['atlassian-domain-verification=', 'atlassian-sending-domain-verification='] },
{ name: 'Apple Business', cats: ['saas'], txt: ['apple-domain-verification='] },
{ name: 'Stripe (verified domain)', cats: ['saas'], txt: ['stripe-verification='] },
{ name: 'DocuSign', cats: ['saas'], txt: ['docusign='] },
{ name: 'Adobe', cats: ['saas'], txt: ['adobe-idp-site-verification=', 'adobe-sign-verification='] },
{ name: 'Slack', cats: ['saas'], txt: ['slack-domain-verification='] },
{ name: 'Zoom', cats: ['saas'], txt: ['zoom-domain-verification', 'ZOOM_verify_'] },
{ name: 'Dropbox', cats: ['saas'], txt: ['dropbox-domain-verification='] },
{ name: 'Cisco Webex', cats: ['saas'], txt: ['webexdomainverification', 'cisco-ci-domain-verification='] },
{ name: 'OpenAI', cats: ['saas'], txt: ['openai-domain-verification='] },
{ name: 'Anthropic', cats: ['saas'], txt: ['anthropic-domain-verification'] },
{ name: 'GitHub', cats: ['saas'], txt: ['_github-challenge', 'github-verification='] },
{ name: 'Miro', cats: ['saas'], txt: ['miro-verification='] },
{ name: 'Notion (verified domain)', cats: ['saas'], txt: ['notion-domain-verification='] },
{ name: 'Figma', cats: ['saas'], txt: ['figma-domain-verification='] },
{ name: 'Canva', cats: ['saas'], txt: ['canva-site-verification='] },
{ name: 'Have I Been Pwned', cats: ['saas'], txt: ['have-i-been-pwned-verification='] },
{ name: 'Okta', cats: ['saas', 'auth'], txt: ['okta-verification='] },
{ name: 'Twilio', cats: ['saas'], txt: ['twilio-domain-verification='] },
{ name: 'Postman', cats: ['saas'], txt: ['postman-domain-verification='] },
{ name: 'Mongo Atlas', cats: ['saas'], txt: ['mongodb-site-verification='] },
{ name: 'Loom', cats: ['saas'], txt: ['loom-site-verification='] },
{ name: 'Intercom (verified domain)', cats: ['saas'], txt: ['intercom-domain-verification'] },
{ name: 'Shopify (verified domain)', cats: ['saas'], txt: ['shopify-verification-code='] },
{ name: 'Wix (verified domain)', cats: ['saas'], txt: ['wix-verification='] },
];
agentgate-source: code mirror on Cloudflare Pages. All repos