Back to blog
InspectionJanuary 1, 2024Β· 14 min read

Website Technology Stack Detection: Uncover What Powers Any Site

A practical Fusebox guide to website technology stack detection.

Website Technology Stack Detection: Uncover What Powers Any Site

Published: January 2024
Reading time: 9 minutes

Every website leaves digital fingerprints. From the JavaScript framework to the hosting provider, each technology choice reveals itself through patterns, headers, and behaviors. Here's how to detect any website's tech stack and understand what it means for performance and security.

Why Stack Detection Matters

Strategic Intelligence

  • Competitive analysis - Know exactly what competitors use
  • Migration planning - Understand current stack before changes
  • Security assessment - Each technology has known vulnerabilities
  • Performance insights - Some stacks are inherently faster
  • Integration compatibility - Ensure third-party services work

Real-World Applications

Developer: "What CMS does this site use?"
Security: "Is this running an outdated framework?"
Business: "Can we build something similar?"
Support: "Why is this integration failing?"
Sales: "What technologies does the prospect use?"

Quick Stack Detection

1. Instant Technology Finder

// Detect technologies on current page
(function detectTechStack() {
  console.log('πŸ” Technology Stack Detection\n');
  
  const detected = {
    frontend: {},
    backend: {},
    infrastructure: {},
    analytics: {},
    security: {},
    cms: {}
  };
  
  // 1. Frontend Framework Detection
  console.log('1️⃣ Frontend Technologies:');
  
  // React
  if (window.React || document.querySelector('[data-reactroot]') || 
      window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
    detected.frontend.React = {
      version: window.React?.version || 'Unknown',
      devTools: !!window.__REACT_DEVTOOLS_GLOBAL_HOOK__
    };
    console.log(`  βš›οΈ React ${detected.frontend.React.version}`);
  }
  
  // Vue.js
  if (window.Vue || document.querySelector('[data-v-]')) {
    const vueVersion = window.Vue?.version || 
                      document.querySelector('[data-server-rendered]') ? '2.x/3.x SSR' : 'Unknown';
    detected.frontend.Vue = { version: vueVersion };
    console.log(`  🟒 Vue.js ${vueVersion}`);
  }
  
  // Angular
  if (window.ng || window.angular || document.querySelector('[ng-version]')) {
    const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version') || 
                     window.angular?.version?.full || 'Unknown';
    detected.frontend.Angular = { version: ngVersion };
    console.log(`  πŸ”Ί Angular ${ngVersion}`);
  }
  
  // jQuery
  if (window.jQuery || window.$) {
    detected.frontend.jQuery = { 
      version: window.jQuery?.fn?.jquery || 'Unknown',
      plugins: []
    };
    console.log(`  πŸ’² jQuery ${detected.frontend.jQuery.version}`);
    
    // Detect jQuery plugins
    if (window.jQuery) {
      const plugins = Object.keys(jQuery.fn).filter(key => 
        !['init', 'constructor', 'jquery'].includes(key)
      ).slice(0, 5);
      if (plugins.length > 0) {
        console.log(`     Plugins: ${plugins.join(', ')}`);
      }
    }
  }
  
  // Next.js
  if (window.__NEXT_DATA__ || document.querySelector('[id="__next"]')) {
    detected.frontend.NextJS = {
      version: window.__NEXT_DATA__?.buildId || 'Unknown',
      isSSG: !!window.__NEXT_DATA__?.gssp,
      isSSR: !!window.__NEXT_DATA__?.props
    };
    console.log(`  β–² Next.js (${detected.frontend.NextJS.isSSG ? 'SSG' : 'SSR'})`);
  }
  
  // Gatsby
  if (window.___gatsby || document.querySelector('[id="___gatsby"]')) {
    detected.frontend.Gatsby = { detected: true };
    console.log('  🟣 Gatsby');
  }
  
  // Svelte
  if (document.querySelector('[class*="svelte-"]')) {
    detected.frontend.Svelte = { detected: true };
    console.log('  🟠 Svelte');
  }
  
  // 2. CSS Framework Detection
  console.log('\n2️⃣ CSS Frameworks:');
  
  const cssFrameworks = {
    Bootstrap: {
      check: () => window.bootstrap || document.querySelector('[class*="col-md-"]'),
      version: () => window.bootstrap?.VERSION
    },
    Tailwind: {
      check: () => document.querySelector('[class*="flex "][class*="items-"][class*="justify-"]'),
      version: () => 'Unknown'
    },
    Bulma: {
      check: () => document.querySelector('[class*="columns "][class*="column "]'),
      version: () => 'Unknown'
    },
    Foundation: {
      check: () => window.Foundation || document.querySelector('[class*="small-"][class*="medium-"]'),
      version: () => window.Foundation?.version
    },
    MaterialUI: {
      check: () => document.querySelector('[class*="MuiButton-"][class*="MuiPaper-"]'),
      version: () => 'Unknown'
    }
  };
  
  Object.entries(cssFrameworks).forEach(([name, framework]) => {
    if (framework.check()) {
      const version = framework.version();
      detected.frontend[name] = { version };
      console.log(`  🎨 ${name} ${version || ''}`);
    }
  });
  
  // 3. Backend/Server Detection
  console.log('\n3️⃣ Backend Detection:');
  
  // Server headers (would need to be fetched)
  fetch(window.location.href, { method: 'HEAD' })
    .then(response => {
      const server = response.headers.get('server');
      const poweredBy = response.headers.get('x-powered-by');
      
      if (server) {
        console.log(`  πŸ–₯️ Server: ${server}`);
        detected.backend.server = server;
      }
      if (poweredBy) {
        console.log(`  ⚑ Powered By: ${poweredBy}`);
        detected.backend.poweredBy = poweredBy;
      }
    })
    .catch(() => {});
  
  // CMS Detection
  console.log('\n4️⃣ CMS Detection:');
  
  // WordPress
  if (document.querySelector('meta[name="generator"][content*="WordPress"]') ||
      document.querySelector('link[href*="wp-content"]') ||
      document.querySelector('link[href*="wp-includes"]')) {
    const wpVersion = document.querySelector('meta[name="generator"]')?.content?.match(/WordPress ([\d.]+)/)?.[1];
    detected.cms.WordPress = { version: wpVersion || 'Unknown' };
    console.log(`  πŸ“ WordPress ${wpVersion || ''}`);
    
    // Detect WP plugins
    const wpPlugins = [];
    document.querySelectorAll('link[href*="wp-content/plugins"]').forEach(link => {
      const plugin = link.href.match(/plugins\/([^\/]+)/)?.[1];
      if (plugin && !wpPlugins.includes(plugin)) {
        wpPlugins.push(plugin);
      }
    });
    if (wpPlugins.length > 0) {
      console.log(`     Plugins: ${wpPlugins.slice(0, 3).join(', ')}`);
    }
  }
  
  // Shopify
  if (window.Shopify || document.querySelector('[id="shopify-features"]')) {
    detected.cms.Shopify = { detected: true };
    console.log('  πŸ›οΈ Shopify');
  }
  
  // Wix
  if (document.querySelector('[href*=".wix.com"]') || window.wixBiSession) {
    detected.cms.Wix = { detected: true };
    console.log('  🎯 Wix');
  }
  
  // Squarespace
  if (window.Squarespace || document.querySelector('[class*="sqs-"]')) {
    detected.cms.Squarespace = { detected: true };
    console.log('  ⬛ Squarespace');
  }
  
  // 5. Analytics & Tracking
  console.log('\n5️⃣ Analytics & Tracking:');
  
  // Google Analytics
  if (window.ga || window.gtag || window.google_analytics_uacct) {
    const gaVersion = window.gtag ? 'GA4' : 'Universal Analytics';
    detected.analytics.GoogleAnalytics = { version: gaVersion };
    console.log(`  πŸ“Š Google Analytics (${gaVersion})`);
  }
  
  // Google Tag Manager
  if (window.google_tag_manager || document.querySelector('[src*="googletagmanager.com"]')) {
    detected.analytics.GTM = { detected: true };
    console.log('  🏷️ Google Tag Manager');
  }
  
  // Facebook Pixel
  if (window._fbq || window.fbq) {
    detected.analytics.FacebookPixel = { detected: true };
    console.log('  πŸ“˜ Facebook Pixel');
  }
  
  // Hotjar
  if (window.hj || window._hjSettings) {
    detected.analytics.Hotjar = { detected: true };
    console.log('  πŸ”₯ Hotjar');
  }
  
  // 6. Infrastructure
  console.log('\n6️⃣ Infrastructure & CDN:');
  
  // Cloudflare
  if (window.__CF || document.querySelector('[data-cf-beacon]')) {
    detected.infrastructure.Cloudflare = { detected: true };
    console.log('  ☁️ Cloudflare');
  }
  
  // Check for CDN by analyzing resource URLs
  const cdnPatterns = {
    'CloudFront': /cloudfront\.net/,
    'Fastly': /fastly\.net/,
    'Akamai': /akamaihd\.net/,
    'MaxCDN': /maxcdn\.com/,
    'jsDelivr': /jsdelivr\.net/,
    'unpkg': /unpkg\.com/
  };
  
  const resources = performance.getEntriesByType('resource');
  const detectedCDNs = new Set();
  
  resources.forEach(resource => {
    Object.entries(cdnPatterns).forEach(([cdn, pattern]) => {
      if (pattern.test(resource.name)) {
        detectedCDNs.add(cdn);
      }
    });
  });
  
  detectedCDNs.forEach(cdn => {
    console.log(`  🌐 ${cdn} CDN`);
    detected.infrastructure[cdn] = { detected: true };
  });
  
  // Summary
  console.log('\nπŸ“‹ Detection Summary:');
  let totalDetected = 0;
  Object.entries(detected).forEach(([category, items]) => {
    const count = Object.keys(items).length;
    if (count > 0) {
      totalDetected += count;
      console.log(`  ${category}: ${count} technologies`);
    }
  });
  
  console.log(`\nTotal technologies detected: ${totalDetected}`);
  
  return detected;
})();

2. Deep Framework Analysis

// Analyze framework versions and configurations
function analyzeFrameworks() {
  console.log('\nπŸ”¬ Deep Framework Analysis\n');
  
  // React Analysis
  if (window.React || window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
    console.log('βš›οΈ React Framework Analysis:');
    
    // Check React version
    const reactVersion = window.React?.version || 'Unknown';
    console.log(`  Version: ${reactVersion}`);
    
    // Check for React Router
    if (window.ReactRouter || document.querySelector('[class*="react-router"]')) {
      console.log('  βœ… React Router detected');
    }
    
    // Check for Redux
    if (window.__REDUX_DEVTOOLS_EXTENSION__ || window.Redux) {
      console.log('  βœ… Redux state management');
      if (window.__REDUX_DEVTOOLS_EXTENSION__) {
        console.log('    πŸ”§ Redux DevTools enabled');
      }
    }
    
    // Check for Material-UI
    if (document.querySelector('[class*="MuiButton-"]')) {
      console.log('  βœ… Material-UI components');
    }
    
    // Performance mode
    if (window._REACT_FIBER_) {
      console.log('  βœ… React Fiber enabled');
    }
    
    // Server-side rendering
    if (document.querySelector('[data-reactroot]')?.innerHTML.length > 1000) {
      console.log('  βœ… Likely server-side rendered');
    }
  }
  
  // Vue.js Analysis
  if (window.Vue || document.querySelector('[data-v-]')) {
    console.log('\n🟒 Vue.js Framework Analysis:');
    
    // Vue version and mode
    if (window.Vue) {
      console.log(`  Version: ${window.Vue.version}`);
      console.log(`  Dev mode: ${window.Vue.config?.devtools || false}`);
    }
    
    // Vuex detection
    if (window.$nuxt?.$store || document.querySelector('[data-v-][data-server-rendered]')) {
      console.log('  βœ… Vuex state management');
    }
    
    // Nuxt.js detection
    if (window.$nuxt || window.__NUXT__) {
      console.log('  βœ… Nuxt.js framework');
      if (window.__NUXT__?.config) {
        console.log(`    Mode: ${window.__NUXT__.config.mode || 'universal'}`);
      }
    }
    
    // Vue Router
    if (window.$nuxt?.$router || window.VueRouter) {
      console.log('  βœ… Vue Router');
    }
  }
  
  // Angular Analysis
  if (window.ng || window.angular || document.querySelector('[ng-version]')) {
    console.log('\nπŸ”Ί Angular Framework Analysis:');
    
    const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version');
    if (ngVersion) {
      console.log(`  Version: Angular ${ngVersion}`);
    } else if (window.angular) {
      console.log(`  Version: AngularJS ${window.angular.version.full}`);
    }
    
    // Angular Universal (SSR)
    if (document.querySelector('[ng-server-context]')) {
      console.log('  βœ… Angular Universal (SSR)');
    }
    
    // Check for common Angular libraries
    if (window.ng?.probe) {
      console.log('  πŸ”§ Angular DevTools available');
    }
  }
  
  // Build tool detection
  console.log('\nπŸ› οΈ Build Tools & Bundlers:');
  
  // Webpack
  if (window.webpackJsonp || window.webpackChunk) {
    console.log('  πŸ“¦ Webpack');
    
    // Check for hot module replacement
    if (window.__webpack_require__?.hmr) {
      console.log('    πŸ”₯ Hot Module Replacement enabled');
    }
  }
  
  // Vite
  if (document.querySelector('[type="module"][src*="@vite"]') || window.__vite__) {
    console.log('  ⚑ Vite');
  }
  
  // Parcel
  if (window.parcelRequire) {
    console.log('  πŸ“¦ Parcel');
  }
}

analyzeFrameworks();

3. Backend Technology Detection

// Detect backend technologies from client-side clues
async function detectBackend() {
  console.log('\nπŸ–₯️ Backend Technology Detection\n');
  
  const backend = {
    language: null,
    framework: null,
    server: null,
    features: []
  };
  
  try {
    // Make a HEAD request to check headers
    const response = await fetch(window.location.href, { method: 'HEAD' });
    const headers = {};
    
    // Collect all headers
    for (let [key, value] of response.headers.entries()) {
      headers[key.toLowerCase()] = value;
    }
    
    console.log('πŸ“‹ Response Headers Analysis:');
    
    // Server detection
    if (headers.server) {
      console.log(`\nServer: ${headers.server}`);
      backend.server = headers.server;
      
      // Parse server header
      if (headers.server.includes('nginx')) {
        console.log('  β†’ Nginx web server');
      } else if (headers.server.includes('Apache')) {
        console.log('  β†’ Apache web server');
      } else if (headers.server.includes('cloudflare')) {
        console.log('  β†’ Cloudflare proxy');
      } else if (headers.server.includes('Microsoft-IIS')) {
        console.log('  β†’ Microsoft IIS');
      }
    }
    
    // Language/Framework detection
    if (headers['x-powered-by']) {
      console.log(`\nPowered By: ${headers['x-powered-by']}`);
      
      const poweredBy = headers['x-powered-by'].toLowerCase();
      
      if (poweredBy.includes('php')) {
        backend.language = 'PHP';
        console.log('  β†’ PHP backend');
      } else if (poweredBy.includes('asp.net')) {
        backend.language = 'C#';
        backend.framework = 'ASP.NET';
        console.log('  β†’ ASP.NET framework');
      } else if (poweredBy.includes('express')) {
        backend.language = 'Node.js';
        backend.framework = 'Express';
        console.log('  β†’ Express.js framework');
      }
    }
    
    // Session cookie analysis
    console.log('\nπŸͺ Session Cookie Analysis:');
    const cookies = document.cookie.split(';');
    
    cookies.forEach(cookie => {
      const [name] = cookie.trim().split('=');
      
      // PHP session
      if (name === 'PHPSESSID') {
        backend.language = backend.language || 'PHP';
        console.log('  β†’ PHP session detected');
      }
      // ASP.NET session
      else if (name === 'ASP.NET_SessionId') {
        backend.language = backend.language || 'C#';
        backend.framework = backend.framework || 'ASP.NET';
        console.log('  β†’ ASP.NET session detected');
      }
      // Java session
      else if (name === 'JSESSIONID') {
        backend.language = backend.language || 'Java';
        console.log('  β†’ Java session detected');
      }
      // Rails session
      else if (name.includes('_session') && name.includes('rails')) {
        backend.language = backend.language || 'Ruby';
        backend.framework = backend.framework || 'Rails';
        console.log('  β†’ Ruby on Rails session detected');
      }
      // Django session
      else if (name === 'sessionid' || name === 'csrftoken') {
        backend.language = backend.language || 'Python';
        backend.framework = backend.framework || 'Django';
        console.log('  β†’ Django session detected');
      }
    });
    
    // URL patterns
    console.log('\nπŸ”— URL Pattern Analysis:');
    const urlPatterns = {
      '.php': 'PHP',
      '.asp': 'ASP Classic',
      '.aspx': 'ASP.NET',
      '.jsp': 'Java/JSP',
      '.do': 'Java/Struts',
      '.cgi': 'CGI Script',
      '.pl': 'Perl',
      '.py': 'Python',
      '.rb': 'Ruby'
    };
    
    const currentPath = window.location.pathname;
    Object.entries(urlPatterns).forEach(([ext, tech]) => {
      if (currentPath.includes(ext)) {
        console.log(`  β†’ ${tech} detected from URL`);
        backend.language = backend.language || tech.split('/')[0];
      }
    });
    
    // API endpoint patterns
    console.log('\nπŸ”Œ API Endpoint Patterns:');
    
    // Look for common API patterns in the page
    const apiPatterns = [
      { pattern: /\/api\/v\d+/, tech: 'RESTful API versioning' },
      { pattern: /\/graphql/, tech: 'GraphQL API' },
      { pattern: /\/rest\//, tech: 'REST API' },
      { pattern: /\/_api\//, tech: 'SharePoint API' },
      { pattern: /\/odata\//, tech: 'OData API' },
      { pattern: /\/jsonrpc/, tech: 'JSON-RPC API' }
    ];
    
    const pageContent = document.documentElement.innerHTML;
    apiPatterns.forEach(({ pattern, tech }) => {
      if (pattern.test(pageContent)) {
        console.log(`  β†’ ${tech}`);
        backend.features.push(tech);
      }
    });
    
  } catch (error) {
    console.log('❌ Could not fetch headers (CORS)');
  }
  
  // Error page signatures
  console.log('\n⚠️ Error Page Signatures:');
  
  // Create a hidden iframe to test 404 page
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.src = '/this-page-definitely-does-not-exist-404-test';
  
  iframe.onload = () => {
    try {
      const errorContent = iframe.contentDocument?.body?.innerHTML || '';
      
      // Check for framework-specific error pages
      if (errorContent.includes('Whitelabel Error Page')) {
        console.log('  β†’ Spring Boot detected');
        backend.framework = 'Spring Boot';
      } else if (errorContent.includes('django.core.exceptions')) {
        console.log('  β†’ Django detected');
        backend.framework = 'Django';
      } else if (errorContent.includes('Rails.root')) {
        console.log('  β†’ Ruby on Rails detected');
        backend.framework = 'Rails';
      }
    } catch (e) {
      // Can't access iframe content (different origin)
    }
    
    document.body.removeChild(iframe);
  };
  
  document.body.appendChild(iframe);
  
  // Summary
  setTimeout(() => {
    console.log('\nπŸ“Š Backend Detection Summary:');
    console.log(`Language: ${backend.language || 'Unknown'}`);
    console.log(`Framework: ${backend.framework || 'Unknown'}`);
    console.log(`Server: ${backend.server || 'Unknown'}`);
    if (backend.features.length > 0) {
      console.log(`Features: ${backend.features.join(', ')}`);
    }
  }, 2000);
  
  return backend;
}

detectBackend();

Security Implications

1. Version Vulnerability Scanner

// Check for known vulnerabilities in detected versions
function scanVulnerabilities() {
  console.log('\nπŸ›‘οΈ Vulnerability Scanner\n');
  
  const vulnerabilities = [];
  
  // jQuery version check
  if (window.jQuery) {
    const version = window.jQuery.fn.jquery;
    const [major, minor, patch] = version.split('.').map(Number);
    
    console.log(`jQuery ${version} detected`);
    
    if (major < 3 || (major === 3 && minor < 5)) {
      vulnerabilities.push({
        component: 'jQuery',
        version: version,
        severity: 'HIGH',
        cve: 'CVE-2020-11022',
        description: 'XSS vulnerability in jQuery < 3.5.0'
      });
    }
  }
  
  // Angular version check
  const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version');
  if (ngVersion) {
    const majorVersion = parseInt(ngVersion.split('.')[0]);
    
    console.log(`Angular ${ngVersion} detected`);
    
    if (majorVersion < 11) {
      vulnerabilities.push({
        component: 'Angular',
        version: ngVersion,
        severity: 'MEDIUM',
        description: 'Outdated Angular version, missing security updates'
      });
    }
  }
  
  // WordPress detection
  const wpGenerator = document.querySelector('meta[name="generator"][content*="WordPress"]');
  if (wpGenerator) {
    const wpVersion = wpGenerator.content.match(/WordPress ([\d.]+)/)?.[1];
    if (wpVersion) {
      console.log(`WordPress ${wpVersion} detected`);
      
      const [major, minor] = wpVersion.split('.').map(Number);
      if (major < 5 || (major === 5 && minor < 8)) {
        vulnerabilities.push({
          component: 'WordPress',
          version: wpVersion,
          severity: 'CRITICAL',
          description: 'Multiple vulnerabilities in WordPress < 5.8'
        });
      }
    }
  }
  
  // Check for outdated TLS
  if (window.location.protocol === 'https:') {
    // This would need server access to check properly
    console.log('HTTPS enabled - TLS version check requires server access');
  } else {
    vulnerabilities.push({
      component: 'Protocol',
      severity: 'CRITICAL',
      description: 'Site not using HTTPS'
    });
  }
  
  // Report vulnerabilities
  if (vulnerabilities.length > 0) {
    console.log('\n❌ VULNERABILITIES FOUND:');
    console.log('─'.repeat(50));
    
    vulnerabilities.forEach(vuln => {
      const icon = vuln.severity === 'CRITICAL' ? 'πŸ”΄' :
                  vuln.severity === 'HIGH' ? '🟠' :
                  vuln.severity === 'MEDIUM' ? '🟑' : '🟒';
      
      console.log(`\n${icon} ${vuln.component} ${vuln.version || ''}`);
      console.log(`Severity: ${vuln.severity}`);
      if (vuln.cve) console.log(`CVE: ${vuln.cve}`);
      console.log(`Details: ${vuln.description}`);
    });
    
    console.log('\nπŸ’‘ Recommendations:');
    console.log('1. Update all components to latest stable versions');
    console.log('2. Enable automatic security updates where possible');
    console.log('3. Subscribe to security advisories for your stack');
    console.log('4. Perform regular security audits');
  } else {
    console.log('βœ… No known vulnerabilities detected');
    console.log('Note: This is not a comprehensive security audit');
  }
  
  return vulnerabilities;
}

scanVulnerabilities();

2. Technology Risk Assessment

// Assess risks associated with detected technologies
function assessTechnologyRisks() {
  console.log('\n⚠️ Technology Risk Assessment\n');
  
  const risks = {
    high: [],
    medium: [],
    low: []
  };
  
  // Check for risky configurations
  
  // 1. Debug mode indicators
  if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || 
      window.Vue?.config?.devtools ||
      window.angular?.debug) {
    risks.high.push({
      issue: 'Debug mode enabled in production',
      impact: 'Exposes internal application state and structure',
      solution: 'Disable debug tools in production builds'
    });
  }
  
  // 2. Source maps
  const scripts = document.querySelectorAll('script[src]');
  let hasSourceMaps = false;
  
  scripts.forEach(script => {
    if (script.src.includes('.map') || script.innerHTML.includes('sourceMappingURL')) {
      hasSourceMaps = true;
    }
  });
  
  if (hasSourceMaps) {
    risks.medium.push({
      issue: 'Source maps exposed',
      impact: 'Original source code visible to attackers',
      solution: 'Remove source maps from production'
    });
  }
  
  // 3. Outdated libraries
  if (window.jQuery && window.jQuery.fn.jquery.startsWith('1.')) {
    risks.high.push({
      issue: 'Severely outdated jQuery version',
      impact: 'Multiple known security vulnerabilities',
      solution: 'Upgrade to jQuery 3.x or remove dependency'
    });
  }
  
  // 4. Mixed content
  if (window.location.protocol === 'https:') {
    const httpResources = document.querySelectorAll('[src^="http:"], [href^="http:"]');
    if (httpResources.length > 0) {
      risks.high.push({
        issue: 'Mixed content (HTTP resources on HTTPS page)',
        impact: 'Breaks security guarantees of HTTPS',
        solution: 'Use HTTPS for all resources'
      });
    }
  }
  
  // 5. Exposed API keys
  const scriptContent = Array.from(scripts).map(s => s.innerHTML).join(' ');
  const apiKeyPatterns = [
    /api[_-]?key['"]\s*[:=]\s*['"][^'"]{20,}/i,
    /['"](AIza[0-9A-Za-z-_]{35})['"]/, // Google
    /['"](sk_live_[0-9a-zA-Z]{24,})['"]/, // Stripe
    /['"](pk_live_[0-9a-zA-Z]{24,})['"]/ // Stripe public
  ];
  
  apiKeyPatterns.forEach(pattern => {
    if (pattern.test(scriptContent)) {
      risks.high.push({
        issue: 'Potential API key exposed in JavaScript',
        impact: 'API abuse, data theft, financial loss',
        solution: 'Move API keys to server-side, use proxy endpoints'
      });
    }
  });
  
  // 6. Technology-specific risks
  
  // WordPress without hardening
  if (document.querySelector('link[href*="wp-content"]')) {
    if (document.querySelector('link[href*="/wp-admin"]') || 
        document.querySelector('link[href*="/wp-login"]')) {
      risks.medium.push({
        issue: 'WordPress admin URLs exposed',
        impact: 'Easy target for brute force attacks',
        solution: 'Hide admin URLs, implement 2FA'
      });
    }
  }
  
  // Exposed development frameworks
  if (window.webpackHotUpdate) {
    risks.high.push({
      issue: 'Webpack hot reload in production',
      impact: 'Development server exposed to internet',
      solution: 'Use production build without dev server'
    });
  }
  
  // Report risks
  console.log('πŸ”΄ HIGH RISK ISSUES:');
  if (risks.high.length === 0) {
    console.log('  None found');
  } else {
    risks.high.forEach(risk => {
      console.log(`\n  Issue: ${risk.issue}`);
      console.log(`  Impact: ${risk.impact}`);
      console.log(`  Fix: ${risk.solution}`);
    });
  }
  
  console.log('\n🟑 MEDIUM RISK ISSUES:');
  if (risks.medium.length === 0) {
    console.log('  None found');
  } else {
    risks.medium.forEach(risk => {
      console.log(`\n  Issue: ${risk.issue}`);
      console.log(`  Impact: ${risk.impact}`);
      console.log(`  Fix: ${risk.solution}`);
    });
  }
  
  // Best practices
  console.log('\nπŸ’‘ Security Best Practices:');
  console.log('1. Keep all dependencies updated');
  console.log('2. Use subresource integrity (SRI) for CDN resources');
  console.log('3. Implement Content Security Policy');
  console.log('4. Remove debug code and source maps');
  console.log('5. Audit npm/yarn dependencies regularly');
  
  return risks;
}

assessTechnologyRisks();

Complete Stack Analysis

Comprehensive Technology Audit

// Run complete technology stack audit
async function completeTechAudit() {
  console.log('πŸ” COMPLETE TECHNOLOGY STACK AUDIT');
  console.log('═'.repeat(50));
  console.log(`URL: ${window.location.href}`);
  console.log(`Date: ${new Date().toLocaleDateString()}\n`);
  
  const audit = {
    frontend: {},
    backend: {},
    infrastructure: {},
    security: {},
    performance: {},
    score: 100
  };
  
  // Phase 1: Frontend Detection
  console.log('πŸ“± PHASE 1: FRONTEND TECHNOLOGIES');
  console.log('─'.repeat(40));
  
  // Detect all frontend technologies
  const frontendChecks = {
    React: window.React || window.__REACT_DEVTOOLS_GLOBAL_HOOK__,
    Vue: window.Vue || document.querySelector('[data-v-]'),
    Angular: window.angular || document.querySelector('[ng-version]'),
    jQuery: window.jQuery || window.$,
    Bootstrap: window.bootstrap || document.querySelector('[class*="col-md-"]'),
    Tailwind: document.querySelector('[class*="flex "][class*="items-"]')
  };
  
  Object.entries(frontendChecks).forEach(([tech, detected]) => {
    if (detected) {
      audit.frontend[tech] = { detected: true };
      console.log(`βœ… ${tech}`);
    }
  });
  
  // Phase 2: Performance Impact
  console.log('\n⚑ PHASE 2: PERFORMANCE IMPACT');
  console.log('─'.repeat(40));
  
  const resources = performance.getEntriesByType('resource');
  const jsSize = resources
    .filter(r => r.name.includes('.js'))
    .reduce((sum, r) => sum + (r.transferSize || 0), 0);
  const cssSize = resources
    .filter(r => r.name.includes('.css'))
    .reduce((sum, r) => sum + (r.transferSize || 0), 0);
  
  console.log(`JavaScript: ${(jsSize / 1024).toFixed(0)}KB`);
  console.log(`CSS: ${(cssSize / 1024).toFixed(0)}KB`);
  console.log(`Total resources: ${resources.length}`);
  
  if (jsSize > 500000) {
    audit.performance.jsSize = 'Too large';
    audit.score -= 10;
    console.log('⚠️ JavaScript bundle too large');
  }
  
  // Phase 3: Security Analysis
  console.log('\nπŸ”’ PHASE 3: SECURITY ANALYSIS');
  console.log('─'.repeat(40));
  
  // Check for security issues
  const securityChecks = {
    HTTPS: window.location.protocol === 'https:',
    'Debug Mode': !!(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || window.Vue?.config?.devtools),
    'Source Maps': Array.from(document.scripts).some(s => s.src.includes('.map')),
    'Console Logs': window.console.log.toString() !== 'function log() { [native code] }'
  };
  
  Object.entries(securityChecks).forEach(([check, result]) => {
    audit.security[check] = result;
    if (check === 'HTTPS' && !result) {
      console.log('❌ Not using HTTPS');
      audit.score -= 20;
    } else if (check !== 'HTTPS' && result) {
      console.log(`⚠️ ${check} detected`);
      audit.score -= 5;
    } else if (check === 'HTTPS' && result) {
      console.log('βœ… HTTPS enabled');
    }
  });
  
  // Phase 4: Best Practices
  console.log('\nβœ… PHASE 4: BEST PRACTICES');
  console.log('─'.repeat(40));
  
  const practices = {
    'Compression': resources.some(r => r.encodedBodySize < r.decodedBodySize * 0.8),
    'CDN Usage': resources.some(r => r.name.includes('cdn')),
    'Lazy Loading': document.querySelectorAll('img[loading="lazy"]').length > 0,
    'Modern Format': document.querySelectorAll('source[type="image/webp"]').length > 0
  };
  
  Object.entries(practices).forEach(([practice, implemented]) => {
    console.log(`${implemented ? 'βœ…' : '❌'} ${practice}`);
    if (!implemented) audit.score -= 5;
  });
  
  // Final Score
  console.log('\nπŸ“Š AUDIT SUMMARY');
  console.log('═'.repeat(50));
  console.log(`Technology Score: ${audit.score}/100`);
  console.log(`Frontend frameworks: ${Object.keys(audit.frontend).length}`);
  console.log(`Security issues: ${Object.values(audit.security).filter(v => v).length}`);
  
  // Recommendations
  console.log('\nπŸ’‘ RECOMMENDATIONS:');
  
  if (audit.score < 70) {
    console.log('1. Address security vulnerabilities immediately');
  }
  if (jsSize > 500000) {
    console.log('2. Implement code splitting and tree shaking');
  }
  if (!practices['Modern Format']) {
    console.log('3. Use modern image formats (WebP, AVIF)');
  }
  if (!practices['CDN Usage']) {
    console.log('4. Implement CDN for static assets');
  }
  console.log('5. Keep all dependencies updated');
  console.log('6. Remove development code from production');
  
  return audit;
}

// Run the complete audit
completeTechAudit();

The Bottom Line

Technology detection reveals more than just toolsβ€”it exposes:

  • Security posture - Outdated versions mean known vulnerabilities
  • Performance characteristics - Some stacks are inherently slower
  • Development practices - Debug mode in production shows poor deployment
  • Business priorities - Technology choices reflect company values
  • Technical debt - Mixed technologies indicate evolution over time

Know your stack. Update regularly. Remove debug code. Your technology choices are visible to everyone.


Detect any tech stack instantly: Fusebox identifies frameworks, libraries, CMSs, and infrastructure while you browse. Understand what powers any website. $29 one-time purchase.