Debug Websites with Bookmarklets

Professional debugging tools you can use on any website without opening DevTools.

Debugging Made Simple

While browser DevTools are powerful, sometimes you need quick debugging capabilities without the overhead. Bookmarklets provide instant debugging tools that work on any device, including mobile browsers where DevTools aren't available.

🔍 Why Use Debugging Bookmarklets?

  • • Works on devices without DevTools access
  • • Share debugging tools with non-developers
  • • Quick access to common debugging tasks
  • • Visual debugging without console knowledge

DOM and Element Inspection

🎯 Element Inspector

Click any element to see its properties

javascript:(function(){
  document.body.style.cursor = 'crosshair';
  
  function inspect(e) {
    e.preventDefault();
    e.stopPropagation();
    
    var el = e.target;
    var info = {
      tag: el.tagName,
      id: el.id || 'none',
      classes: el.className || 'none',
      dimensions: el.offsetWidth + 'x' + el.offsetHeight,
      position: 'x:' + el.offsetLeft + ' y:' + el.offsetTop
    };
    
    alert(JSON.stringify(info, null, 2));
    document.removeEventListener('click', inspect);
    document.body.style.cursor = 'auto';
  }
  
  document.addEventListener('click', inspect);
})();

📐 Visual Box Model

Show margin, border, and padding for all elements

javascript:(function(){
  var style = document.createElement('style');
  style.innerHTML = `
    * { outline: 1px solid red !important; }
    *:before, *:after { outline: 1px solid blue !important; }
    body * { background-color: rgba(255,0,0,0.05) !important; }
    body * * { background-color: rgba(0,255,0,0.05) !important; }
    body * * * { background-color: rgba(0,0,255,0.05) !important; }
  `;
  document.head.appendChild(style);
  
  setTimeout(() => {
    if(confirm('Remove debugging styles?')) {
      style.remove();
    }
  }, 100);
})();

🌳 DOM Tree Visualizer

Display page structure hierarchy

javascript:(function(){
  function getTree(el, depth = 0) {
    var indent = '  '.repeat(depth);
    var tag = el.tagName?.toLowerCase() || 'text';
    var id = el.id ? '#' + el.id : '';
    var classes = el.className ? '.' + el.className.split(' ').join('.') : '';
    var tree = indent + tag + id + classes + '\n';
    
    if(el.children && depth < 5) {
      Array.from(el.children).forEach(child => {
        tree += getTree(child, depth + 1);
      });
    }
    return tree;
  }
  
  var tree = getTree(document.body);
  var win = window.open('', 'DOM Tree', 'width=600,height=400');
  win.document.write('<pre>' + tree + '</pre>');
})();

CSS and Styling Debug Tools

🎨 Computed Styles Viewer

See all computed styles for clicked element

javascript:(function(){
  document.body.style.cursor = 'help';
  
  function showStyles(e) {
    e.preventDefault();
    var styles = window.getComputedStyle(e.target);
    var output = '';
    
    ['color', 'background-color', 'font-size', 'font-family', 'margin', 
     'padding', 'border', 'width', 'height', 'display', 'position'].forEach(prop => {
      output += prop + ': ' + styles.getPropertyValue(prop) + '\n';
    });
    
    alert('Computed Styles:\n\n' + output);
    document.removeEventListener('click', showStyles);
    document.body.style.cursor = 'auto';
  }
  
  document.addEventListener('click', showStyles);
})();

🔍 CSS Rule Finder

Find which CSS rules apply to an element

javascript:(function(){
  var sheets = document.styleSheets;
  var rules = [];
  
  for(var i = 0; i < sheets.length; i++) {
    try {
      var ruleList = sheets[i].cssRules || sheets[i].rules;
      for(var j = 0; j < ruleList.length; j++) {
        rules.push(ruleList[j].cssText);
      }
    } catch(e) {
      console.log('Cannot access stylesheet:', sheets[i].href);
    }
  }
  
  var search = prompt('Search CSS rules for:');
  if(search) {
    var matches = rules.filter(rule => rule.includes(search));
    var win = window.open('', 'CSS Rules', 'width=800,height=600');
    win.document.write('<pre>' + matches.join('\n\n') + '</pre>');
  }
})();

📱 Responsive Breakpoint Tester

Test common viewport sizes

javascript:(function(){
  var sizes = {
    'Mobile': '375x667',
    'Tablet': '768x1024',
    'Desktop': '1920x1080',
    'Custom': prompt('Enter custom size (WIDTHxHEIGHT):')
  };
  
  var choice = prompt('Choose size: ' + Object.keys(sizes).join(', '));
  var size = sizes[choice];
  
  if(size && size.includes('x')) {
    var [width, height] = size.split('x');
    window.resizeTo(parseInt(width), parseInt(height));
    alert('Viewport resized to: ' + size);
  }
})();

JavaScript and Performance Debugging

🐛 Error Monitor

Catch and display all JavaScript errors

javascript:(function(){
  var errorLog = document.createElement('div');
  errorLog.style = 'position:fixed;bottom:0;right:0;background:#000;color:#f00;' +
                   'padding:10px;max-width:400px;max-height:200px;overflow:auto;' +
                   'z-index:9999;font-family:monospace;font-size:12px;';
  errorLog.innerHTML = '<strong>JS Error Monitor</strong><br>';
  document.body.appendChild(errorLog);
  
  window.onerror = function(msg, url, line, col, error) {
    var errorInfo = new Date().toLocaleTimeString() + ' - ' + msg + 
                    ' (Line: ' + line + ')' + '<br>';
    errorLog.innerHTML += errorInfo;
    return true;
  };
  
  errorLog.onclick = function() {
    if(confirm('Close error monitor?')) {
      errorLog.remove();
      window.onerror = null;
    }
  };
})();

⏱️ Performance Timer

Measure page load and interaction times

javascript:(function(){
  var perf = window.performance;
  var timing = perf.timing;
  var navigation = perf.navigation;
  
  var metrics = {
    'Page Load Time': timing.loadEventEnd - timing.navigationStart,
    'DOM Ready': timing.domContentLoadedEventEnd - timing.navigationStart,
    'Time to First Byte': timing.responseStart - timing.navigationStart,
    'DNS Lookup': timing.domainLookupEnd - timing.domainLookupStart,
    'Server Response': timing.responseEnd - timing.requestStart,
    'DOM Processing': timing.domComplete - timing.domLoading,
    'Resources': perf.getEntriesByType('resource').length
  };
  
  var output = 'Performance Metrics (ms):\n\n';
  for(var key in metrics) {
    output += key + ': ' + metrics[key] + 'ms\n';
  }
  
  alert(output);
})();

📊 Memory Usage Monitor

Track memory consumption over time

javascript:(function(){
  if(!performance.memory) {
    alert('Memory API not available in this browser');
    return;
  }
  
  var monitor = document.createElement('div');
  monitor.style = 'position:fixed;top:0;right:0;background:#000;color:#0f0;' +
                  'padding:10px;font-family:monospace;font-size:12px;z-index:9999;';
  document.body.appendChild(monitor);
  
  var interval = setInterval(() => {
    var mem = performance.memory;
    var used = (mem.usedJSHeapSize / 1048576).toFixed(2);
    var total = (mem.totalJSHeapSize / 1048576).toFixed(2);
    monitor.innerHTML = 'Memory: ' + used + 'MB / ' + total + 'MB';
  }, 1000);
  
  monitor.onclick = () => {
    clearInterval(interval);
    monitor.remove();
  };
})();

Network and Resource Debugging

🌐 Resource Analyzer

List all loaded resources with sizes

javascript:(function(){
  var resources = performance.getEntriesByType('resource');
  var byType = {};
  
  resources.forEach(r => {
    var type = r.name.split('.').pop().split('?')[0] || 'other';
    if(!byType[type]) byType[type] = [];
    byType[type].push({
      name: r.name.split('/').pop(),
      size: (r.transferSize / 1024).toFixed(2) + 'KB',
      time: r.duration.toFixed(0) + 'ms'
    });
  });
  
  var output = '';
  for(var type in byType) {
    output += '\n' + type.toUpperCase() + ' (' + byType[type].length + '):\n';
    byType[type].forEach(r => {
      output += '  ' + r.name + ' - ' + r.size + ' - ' + r.time + '\n';
    });
  }
  
  var win = window.open('', 'Resources', 'width=800,height=600');
  win.document.write('<pre>' + output + '</pre>');
})();

🔗 Broken Link Checker

Find all broken links on the page

javascript:(function(){
  var links = document.querySelectorAll('a[href]');
  var checked = 0;
  var broken = [];
  
  links.forEach(link => {
    fetch(link.href, {method: 'HEAD', mode: 'no-cors'})
      .then(response => {
        checked++;
        if(!response.ok && response.type !== 'opaque') {
          broken.push(link.href);
          link.style.backgroundColor = 'red';
        }
        if(checked === links.length) {
          alert('Found ' + broken.length + ' potentially broken links');
        }
      })
      .catch(() => {
        checked++;
        broken.push(link.href);
        link.style.backgroundColor = 'red';
      });
  });
})();

Accessibility Debugging

♿ Accessibility Checker

Basic accessibility audit

javascript:(function(){
  var issues = [];
  
  // Check images for alt text
  document.querySelectorAll('img').forEach(img => {
    if(!img.alt) {
      issues.push('Image missing alt text: ' + img.src);
      img.style.border = '3px solid red';
    }
  });
  
  // Check form labels
  document.querySelectorAll('input, select, textarea').forEach(input => {
    if(!input.getAttribute('aria-label') && !input.labels?.length) {
      issues.push('Form input missing label: ' + (input.name || input.id));
      input.style.border = '3px solid orange';
    }
  });
  
  // Check heading hierarchy
  var lastLevel = 0;
  document.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach(h => {
    var level = parseInt(h.tagName[1]);
    if(level > lastLevel + 1) {
      issues.push('Heading skip: ' + h.tagName + ' after H' + lastLevel);
      h.style.border = '3px solid yellow';
    }
    lastLevel = level;
  });
  
  alert('Accessibility Issues (' + issues.length + '):\n\n' + issues.join('\n'));
})();

🎯 Focus Order Visualizer

Show tab order of focusable elements

javascript:(function(){
  var focusable = document.querySelectorAll(
    'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  
  var order = 1;
  focusable.forEach(el => {
    var label = document.createElement('div');
    label.style = 'position:absolute;background:red;color:white;' +
                  'padding:2px 6px;font-size:12px;z-index:9999;' +
                  'border-radius:10px;';
    label.innerText = order++;
    
    el.style.position = 'relative';
    el.appendChild(label);
  });
  
  alert('Tab order shown. Numbers indicate focus sequence.');
})();

Mobile Debugging

📱 Mobile-Specific Tools

These bookmarklets are especially useful on mobile devices where traditional DevTools aren't available:

  • • Viewport size display
  • • Touch event debugging
  • • Orientation change detection
  • • Mobile performance metrics
  • • Console log viewer

📱 Mobile Debug Panel

All-in-one mobile debugging tool

javascript:(function(){
  var panel = document.createElement('div');
  panel.style = 'position:fixed;bottom:0;left:0;right:0;background:#000;' +
                'color:#fff;padding:10px;font-size:12px;z-index:9999;';
  
  function update() {
    panel.innerHTML = 
      'Viewport: ' + window.innerWidth + 'x' + window.innerHeight + ' | ' +
      'Screen: ' + screen.width + 'x' + screen.height + ' | ' +
      'DPR: ' + window.devicePixelRatio + ' | ' +
      'Orientation: ' + screen.orientation.type;
  }
  
  update();
  window.addEventListener('resize', update);
  window.addEventListener('orientationchange', update);
  
  panel.onclick = () => {
    panel.remove();
  };
  
  document.body.appendChild(panel);
})();

Creating Custom Debug Tools

These examples demonstrate the power of bookmarklet debugging. You can combine multiple techniques to create custom debugging tools tailored to your specific needs. Consider creating bookmarklets for:

  • Framework-specific debugging (React, Vue, Angular)
  • API response inspection
  • WebSocket monitoring
  • Local storage debugging
  • Service worker inspection
  • Animation performance testing

Debug Like a Pro

Master debugging with bookmarklets and never be without your tools again. Create your own custom debugging utilities or explore more advanced techniques.