Network Sniffer 🌐

Logs XHR, Fetch, WebSocket, and Service Worker requests

// ==UserScript==
// @name         Network Sniffer 🌐
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  Logs XHR, Fetch, WebSocket, and Service Worker requests
// @author       Manu OVG
// @match        *://*/*
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    // 🌍 UI Creation
    let panel = document.createElement('div');
    panel.innerHTML = `
        <style>
            .sniffer-ui {
                position: fixed;
                top: 20px;
                right: 20px;
                width: 400px;
                max-height: 500px;
                background: rgba(30, 30, 30, 0.95);
                color: white;
                font-family: Arial, sans-serif;
                font-size: 12px;
                border-radius: 8px;
                padding: 10px;
                box-shadow: 0 4px 10px rgba(0,0,0,0.3);
                overflow: hidden;
                z-index: 9999;
            }
            .sniffer-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding-bottom: 5px;
                border-bottom: 1px solid #555;
            }
            .sniffer-title { font-weight: bold; }
            .sniffer-close { cursor: pointer; color: red; font-weight: bold; }
            .sniffer-body {
                max-height: 400px;
                overflow-y: auto;
                padding-top: 5px;
            }
            .sniffer-item {
                padding: 5px;
                border-bottom: 1px solid #444;
                word-wrap: break-word;
            }
            .sniffer-get { color: #4CAF50; }  /* Green */
            .sniffer-post { color: #FFC107; } /* Yellow */
            .sniffer-fetch { color: #03A9F4; } /* Blue */
            .sniffer-websocket { color: #FF5722; } /* Red */
            .sniffer-copy {
                background: #008CBA;
                color: white;
                padding: 4px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 10px;
                margin-top: 5px;
            }
            .sniffer-counter {
                font-size: 14px;
                font-weight: bold;
                color: #FFD700;
            }
        </style>
        <div class="sniffer-ui">
            <div class="sniffer-header">
                <span class="sniffer-title">🌐 Network Sniffer (<span class="sniffer-counter">0</span>)</span>
                <span class="sniffer-close">✖</span>
            </div>
            <div class="sniffer-body"></div>
        </div>
    `;

    document.body.appendChild(panel);
    
    let snifferBody = panel.querySelector('.sniffer-body');
    let closeBtn = panel.querySelector('.sniffer-close');
    let counter = panel.querySelector('.sniffer-counter');
    let requestCount = 0;

    // ✖ Close UI on click
    closeBtn.onclick = () => panel.style.display = 'none';

    // 🔥 Function to log requests in UI
    function logRequest(type, method, url) {
        requestCount++;
        counter.innerText = requestCount; // Update request counter
        let colorClass = type === 'GET' ? 'sniffer-get' : type === 'POST' ? 'sniffer-post' : type === 'WebSocket' ? 'sniffer-websocket' : 'sniffer-fetch';
        let requestItem = document.createElement('div');
        requestItem.classList.add('sniffer-item', colorClass);
        requestItem.innerHTML = `
            <b>${type} | ${method}</b> → ${url}
            <button class="sniffer-copy">📋 Copy</button>
        `;

        snifferBody.prepend(requestItem);

        // 📋 Copy URL on click
        requestItem.querySelector('.sniffer-copy').onclick = () => {
            GM_setClipboard(url);
            alert("URL copied!");
        };
    }

    // 🕵️ Intercept XHR requests
    (function(open) {
        XMLHttpRequest.prototype.open = function(method, url) {
            this.addEventListener("load", function() {
                logRequest("XHR", method, url);
            });
            open.apply(this, arguments);
        };
    })(XMLHttpRequest.prototype.open);

    // 🕵️ Intercept Fetch requests
    (function(fetch) {
        window.fetch = function() {
            let url = arguments[0];
            let method = arguments[1] && arguments[1].method ? arguments[1].method.toUpperCase() : 'GET';
            logRequest("Fetch", method, url);
            return fetch.apply(this, arguments);
        };
    })(window.fetch);

    // 🕵️ Capture WebSocket requests
    let originalWebSocket = window.WebSocket;
    window.WebSocket = function(url, protocols) {
        let ws = new originalWebSocket(url, protocols);
        logRequest("WebSocket", "CONNECT", url);
        ws.addEventListener('message', function(event) {
            console.log("WebSocket Message: ", event.data);
        });
        return ws;
    };

    // 🕵️ Capture Service Worker requests
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.addEventListener('message', function(event) {
            logRequest("ServiceWorker", event.data.method, event.data.url);
        });
    }
})();