Skip to content

Instantly share code, notes, and snippets.

@arafathusayn
Last active May 31, 2026 15:35
Show Gist options
  • Select an option

  • Save arafathusayn/101a211b3d8122876d70cf1af04ae81d to your computer and use it in GitHub Desktop.

Select an option

Save arafathusayn/101a211b3d8122876d70cf1af04ae81d to your computer and use it in GitHub Desktop.
Remove Tawk.to Branding (2026)
/**
* Remove Tawk.to Branding
*
* What it hides:
* - Footer branding links (tawk.to, utm_source=tawk-messenger)
* - "Add Chat to your website" link
* - Popout button/icon
* - Branding container classes
*
* Key design decisions:
* - CSS injection over DOM removal (less disruptive, survives re-renders)
* - MutationObserver over setInterval (reacts to changes, no wasted cycles)
* - Debounced re-scans (Tawk rebuilds its widget DOM sometimes)
* - iframe `load` listener stays active (catches SPA navigations)
* - JS fallback for popout buttons (`:has()` unsupported in older browsers)
*/
;(function removeTawkBranding() {
"use strict";
// ── Config ────────────────────────────────────────────────────────────
var STYLE_ID = "hide-tawk-branding";
// NOTE: No `:contains()` (jQuery-only, invalid in browsers).
// No `:has()` in CSS (Firefox < 121, older Safari/Chrome).
// Popout buttons handled via JS fallback below.
var BRANDING_CSS = [
"a[href*='tawk.to'] { display: none !important; }",
"a[href*='utm_source=tawk-messenger'] { display: none !important; }",
"a[title*='Add Chat to your website'] { display: none !important; }",
".tawk-branding { display: none !important; }",
"[class*='tawk-branding'] { display: none !important; }",
".tawk-padding-small { display: none !important; }",
".tawk-icon-popout { display: none !important; }",
].join("\n");
var RETRY_DELAY_MS = 1500;
// ── State ─────────────────────────────────────────────────────────────
var processedIframes = new WeakSet();
var pendingRetries = new Map();
var debounceTimer = null;
// ── Core ──────────────────────────────────────────────────────────────
/**
* Inject a <style> into a document. Returns true on success.
*/
function injectStyle(doc) {
try {
if (!doc || !doc.createElement) return false;
if (doc.getElementById(STYLE_ID)) return true;
var style = doc.createElement("style");
style.id = STYLE_ID;
style.textContent = BRANDING_CSS;
var target = doc.head || doc.documentElement;
if (target) {
target.appendChild(style);
return true;
}
} catch (_) {
// Cross-origin β€” expected.
}
return false;
}
/**
* JS fallback: hide popout buttons for browsers without CSS `:has()`.
*/
function hidePopoutButtons(doc) {
try {
if (!doc || !doc.querySelectorAll) return;
var icons = doc.querySelectorAll(".tawk-icon-popout");
for (var i = 0; i < icons.length; i++) {
var btn = icons[i].closest("button");
if (btn) btn.style.setProperty("display", "none", "important");
}
} catch (_) {}
}
/**
* Inject styles into an iframe. Retries once if contentDocument isn't ready.
*/
function injectIntoIframe(iframe) {
try {
var doc = iframe.contentDocument;
if (!doc) {
// Schedule a single retry if iframe not ready yet
if (!pendingRetries.has(iframe)) {
var timeout = setTimeout(function () {
pendingRetries.delete(iframe);
injectIntoIframe(iframe);
}, RETRY_DELAY_MS);
pendingRetries.set(iframe, timeout);
}
return;
}
injectStyle(doc);
hidePopoutButtons(doc);
} catch (_) {
// Cross-origin β€” expected.
}
}
/**
* Process a chat iframe: mark as processed, inject now, re-inject on reload.
*/
function handleIframe(iframe) {
if (processedIframes.has(iframe)) return;
var title = (iframe.title || "").toLowerCase();
if (title.indexOf("chat") === -1) return;
processedIframes.add(iframe);
// Inject immediately (may already be loaded)
injectIntoIframe(iframe);
// Re-inject on subsequent loads (SPA navigation, widget rebuild).
// Intentionally NOT `{ once: true }` β€” Tawk can reload iframe content.
iframe.addEventListener("load", function () {
injectIntoIframe(iframe);
});
}
/**
* Scan a root document for all chat iframes.
*/
function scanIframes(root) {
try {
var iframes = (root || document).querySelectorAll("iframe");
for (var i = 0; i < iframes.length; i++) {
handleIframe(iframes[i]);
}
} catch (_) {}
}
// ── Observer ──────────────────────────────────────────────────────────
function onMutations(mutations) {
var foundNewIframe = false;
for (var i = 0; i < mutations.length; i++) {
var added = mutations[i].addedNodes;
for (var j = 0; j < added.length; j++) {
var node = added[j];
if (node.nodeName === "IFRAME") {
handleIframe(node);
foundNewIframe = true;
} else if (node.nodeType === 1 && node.querySelectorAll) {
var nested = node.querySelectorAll("iframe");
if (nested.length) {
for (var k = 0; k < nested.length; k++) {
handleIframe(nested[k]);
}
foundNewIframe = true;
}
}
}
}
// Debounced re-scan: Tawk sometimes rebuilds its widget DOM entirely,
// so existing iframes may get new content without a new IFRAME node.
if (foundNewIframe && !debounceTimer) {
debounceTimer = setTimeout(function () {
debounceTimer = null;
scanIframes();
hidePopoutButtons(document);
}, 500);
}
}
// ── Bootstrap ─────────────────────────────────────────────────────────
function start() {
// Main document branding (outside iframes)
injectStyle(document);
hidePopoutButtons(document);
// Initial iframe scan
scanIframes();
// Watch for dynamically added iframes
if (typeof MutationObserver !== "undefined" && document.body) {
var observer = new MutationObserver(onMutations);
observer.observe(document.body, { childList: true, subtree: true });
// Cleanup
window.addEventListener("beforeunload", function () {
observer.disconnect();
pendingRetries.forEach(clearTimeout);
pendingRetries.clear();
if (debounceTimer) {
clearTimeout(debounceTimer);
debounceTimer = null;
}
});
}
}
// Guard: script may be in <head> before document.body exists
if (document.body) {
start();
} else {
document.addEventListener("DOMContentLoaded", start);
}
})();
@hoangbits

Copy link
Copy Markdown

any of you guys interested in a product that dont force using their logo?

@bloodykheeng

Copy link
Copy Markdown

Have u made ur own app @hoangbits

@hazelcorp2011-cmd

Copy link
Copy Markdown

Please provide new tawk-chat brand removing code because previous code not working..

Below mentioned script not working currently.

<script> var removeBranding = function() { try { const style = document.createElement('style'); style.textContent = '.tawk-padding-small {display:none !important;}'; document.querySelector('iframe[title*="chat"]:nth-child(2)').contentDocument.head.appendChild(style) } catch (e) {} } var tick = 100 setInterval(removeBranding, tick) </script>

@muchisx

muchisx commented May 15, 2026

Copy link
Copy Markdown

@arafathusayn any updates on a new version β˜€οΈ? Seems like the current one no longer works

@bloodykheeng

bloodykheeng commented May 18, 2026

Copy link
Copy Markdown

@hazelcorp2011-cmd πŸ”§ try this β€” it seems the Tawk guys were smart πŸ˜„ they removed the href, so you can’t easily target it anymore with:

a[href*="tawk.to"]

But haha πŸ˜„πŸ˜„πŸ˜„πŸ˜„πŸ˜„ you can still catch that anchor using other CSS attribute selectors. See below πŸ‘‡

method one just hiding the brand

  // ================== embed tawk.to script ==================
  useEffect(() => {
        const BRANDING_SELECTORS = `
        /* expanded widget branding */
        a[style*="font-size: 12px"][style*="font-weight: 400"][style*="padding: 0.5em"],

        /* minimized widget branding */
        a[style*="font-size: 12px"][style*="border-radius: 100px"]
    `;



        const injectStyle = (doc: Document) => {
            if (doc.getElementById("hide-tawk-branding")) return;

            const style = doc.createElement("style");
            style.id = "hide-tawk-branding";

            style.textContent = `
            ${BRANDING_SELECTORS} {
                display: none !important;
                visibility: hidden !important;
                opacity: 0 !important;
                pointer-events: none !important;
                width: 0 !important;
                height: 0 !important;
                overflow: hidden !important;
                max-width: 0 !important;
                max-height: 0 !important;
            }
        `;

            (doc.head || doc.documentElement).prepend(style);
        };

        const handleIframe = (iframe: HTMLIFrameElement) => {
            const apply = () => {
                try {
                    const doc =
                        iframe.contentDocument ||
                        iframe.contentWindow?.document;

                    if (!doc) return;

                    injectStyle(doc);
                } catch {
                    // cross-origin iframe β€” expected for non-tawk iframes
                }
            };

            apply();
            iframe.addEventListener("load", apply);
        };

        // existing iframes
        document.querySelectorAll("iframe").forEach((iframe) => {
            handleIframe(iframe as HTMLIFrameElement);
        });

        // future iframes
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node instanceof HTMLIFrameElement) {
                        handleIframe(node);
                    }

                    if (node instanceof HTMLElement) {
                        node.querySelectorAll("iframe").forEach((iframe) => {
                            handleIframe(iframe as HTMLIFrameElement);
                        });
                    }
                });
            });
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
        });

        return () => {
            observer.disconnect();
        };
    }, []);

method two hiding the brand and adding ur own brand

   // ================== embed tawk.to script ==================
    useEffect(() => {
        if (typeof window === "undefined") return;
        const s1 = document.createElement("script");
        const s0 = document.getElementsByTagName("script")[0];
        s1.async = true;
        s1.src = "Add link to the widget";
        s1.charset = "UTF-8";
        s1.setAttribute("crossorigin", "*");
        s0?.parentNode?.insertBefore(s1, s0);
    }, []);

 // //================ latest hide branding and add ur custom branding =================
     useEffect(() => {
        const BRAND_TEXT = "Powered by bloodykheeng";
        const OVERLAY_ID = "custom-tawk-branding";

        // =========================
        // create stable branding overlay
        // =========================
        let branding = document.getElementById(OVERLAY_ID);

        if (!branding) {
            branding = document.createElement("div");
            branding.id = OVERLAY_ID;
            branding.innerText = BRAND_TEXT;

            Object.assign(branding.style, {
                position: "fixed",
                bottom: "30px",
                right: "100px",
                zIndex: "999999",
                background: "#fff",
                padding: "6px 12px",
                borderRadius: "999px",
                fontSize: "11px",
                color: "#6b7280",
                boxShadow: "0 4px 14px rgba(0,0,0,0.12)",
                pointerEvents: "none",
                transition: "opacity .2s ease",
                opacity: "0",
                visibility: "hidden",
            });

            document.body.appendChild(branding);
        }

        // =========================
        // show/hide overlay
        // =========================
        const showBranding = () => {
            if (!branding) return;

            branding.style.opacity = "1";
            branding.style.visibility = "visible";
        };

        const hideBranding = () => {
            if (!branding) return;

            branding.style.opacity = "0";
            branding.style.visibility = "hidden";
        };

        // =========================
        // tawk callbacks
        // =========================
        const w = window as any;

        w.Tawk_API = w.Tawk_API || {};

        w.Tawk_API.onChatMaximized = showBranding;
        w.Tawk_API.onChatStarted = showBranding;
        w.Tawk_API.onChatMinimized = hideBranding;
        w.Tawk_API.onChatHidden = hideBranding;

        // =========================
        // aggressively hide real branding
        // =========================
        const injectStyle = (doc: Document) => {
            if (doc.getElementById("hide-real-tawk-branding")) return;

            const style = doc.createElement("style");

            style.id = "hide-real-tawk-branding";

            style.textContent = `
            a[style*="font-size: 12px"][style*="padding: 0.5em"],
            a[style*="border-radius: 100px"] {
                opacity: 0 !important;
                visibility: hidden !important;
                pointer-events: none !important;
                transform: scale(0) !important;
            }
        `;

            (doc.head || doc.documentElement).prepend(style);
        };

        const handleIframe = (iframe: HTMLIFrameElement) => {
            const apply = () => {
                try {
                    const doc =
                        iframe.contentDocument ||
                        iframe.contentWindow?.document;

                    if (!doc) return;

                    injectStyle(doc);
                } catch {
                    // cross-origin
                }
            };

            apply();

            iframe.addEventListener("load", apply);
        };

        // existing iframes
        document.querySelectorAll("iframe").forEach((iframe) => {
            handleIframe(iframe as HTMLIFrameElement);
        });

        // future iframes
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node instanceof HTMLIFrameElement) {
                        handleIframe(node);
                    }

                    if (node instanceof HTMLElement) {
                        node.querySelectorAll("iframe").forEach((iframe) => {
                            handleIframe(iframe as HTMLIFrameElement);
                        });
                    }
                });
            });
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
        });

        return () => {
            observer.disconnect();
            branding?.remove();
        };
    }, []);

@hazelcorp2011-cmd

Copy link
Copy Markdown

@hazelcorp2011-cmd πŸ”§ try this β€” it seems the Tawk guys were smart πŸ˜„ they removed the href, so you can’t easily target it anymore with:

a[href*="tawk.to"]

But haha πŸ˜„πŸ˜„πŸ˜„πŸ˜„πŸ˜„ you can still catch that anchor using other CSS attribute selectors. See below πŸ‘‡

method one just hiding the brand

  // ================== embed tawk.to script ==================
  useEffect(() => {
        const BRANDING_SELECTORS = `
        /* expanded widget branding */
        a[style*="font-size: 12px"][style*="font-weight: 400"][style*="padding: 0.5em"],

        /* minimized widget branding */
        a[style*="font-size: 12px"][style*="border-radius: 100px"]
    `;



        const injectStyle = (doc: Document) => {
            if (doc.getElementById("hide-tawk-branding")) return;

            const style = doc.createElement("style");
            style.id = "hide-tawk-branding";

            style.textContent = `
            ${BRANDING_SELECTORS} {
                display: none !important;
                visibility: hidden !important;
                opacity: 0 !important;
                pointer-events: none !important;
                width: 0 !important;
                height: 0 !important;
                overflow: hidden !important;
                max-width: 0 !important;
                max-height: 0 !important;
            }
        `;

            (doc.head || doc.documentElement).prepend(style);
        };

        const handleIframe = (iframe: HTMLIFrameElement) => {
            const apply = () => {
                try {
                    const doc =
                        iframe.contentDocument ||
                        iframe.contentWindow?.document;

                    if (!doc) return;

                    injectStyle(doc);
                } catch {
                    // cross-origin iframe β€” expected for non-tawk iframes
                }
            };

            apply();
            iframe.addEventListener("load", apply);
        };

        // existing iframes
        document.querySelectorAll("iframe").forEach((iframe) => {
            handleIframe(iframe as HTMLIFrameElement);
        });

        // future iframes
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node instanceof HTMLIFrameElement) {
                        handleIframe(node);
                    }

                    if (node instanceof HTMLElement) {
                        node.querySelectorAll("iframe").forEach((iframe) => {
                            handleIframe(iframe as HTMLIFrameElement);
                        });
                    }
                });
            });
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
        });

        return () => {
            observer.disconnect();
        };
    }, []);

method two hiding the brand and adding ur own brand

   // ================== embed tawk.to script ==================
    useEffect(() => {
        if (typeof window === "undefined") return;
        const s1 = document.createElement("script");
        const s0 = document.getElementsByTagName("script")[0];
        s1.async = true;
        s1.src = "Add link to the widget";
        s1.charset = "UTF-8";
        s1.setAttribute("crossorigin", "*");
        s0?.parentNode?.insertBefore(s1, s0);
    }, []);

 // //================ latest hide branding and add ur custom branding =================
     useEffect(() => {
        const BRAND_TEXT = "Powered by bloodykheeng";
        const OVERLAY_ID = "custom-tawk-branding";

        // =========================
        // create stable branding overlay
        // =========================
        let branding = document.getElementById(OVERLAY_ID);

        if (!branding) {
            branding = document.createElement("div");
            branding.id = OVERLAY_ID;
            branding.innerText = BRAND_TEXT;

            Object.assign(branding.style, {
                position: "fixed",
                bottom: "30px",
                right: "100px",
                zIndex: "999999",
                background: "#fff",
                padding: "6px 12px",
                borderRadius: "999px",
                fontSize: "11px",
                color: "#6b7280",
                boxShadow: "0 4px 14px rgba(0,0,0,0.12)",
                pointerEvents: "none",
                transition: "opacity .2s ease",
                opacity: "0",
                visibility: "hidden",
            });

            document.body.appendChild(branding);
        }

        // =========================
        // show/hide overlay
        // =========================
        const showBranding = () => {
            if (!branding) return;

            branding.style.opacity = "1";
            branding.style.visibility = "visible";
        };

        const hideBranding = () => {
            if (!branding) return;

            branding.style.opacity = "0";
            branding.style.visibility = "hidden";
        };

        // =========================
        // tawk callbacks
        // =========================
        const w = window as any;

        w.Tawk_API = w.Tawk_API || {};

        w.Tawk_API.onChatMaximized = showBranding;
        w.Tawk_API.onChatStarted = showBranding;
        w.Tawk_API.onChatMinimized = hideBranding;
        w.Tawk_API.onChatHidden = hideBranding;

        // =========================
        // aggressively hide real branding
        // =========================
        const injectStyle = (doc: Document) => {
            if (doc.getElementById("hide-real-tawk-branding")) return;

            const style = doc.createElement("style");

            style.id = "hide-real-tawk-branding";

            style.textContent = `
            a[style*="font-size: 12px"][style*="padding: 0.5em"],
            a[style*="border-radius: 100px"] {
                opacity: 0 !important;
                visibility: hidden !important;
                pointer-events: none !important;
                transform: scale(0) !important;
            }
        `;

            (doc.head || doc.documentElement).prepend(style);
        };

        const handleIframe = (iframe: HTMLIFrameElement) => {
            const apply = () => {
                try {
                    const doc =
                        iframe.contentDocument ||
                        iframe.contentWindow?.document;

                    if (!doc) return;

                    injectStyle(doc);
                } catch {
                    // cross-origin
                }
            };

            apply();

            iframe.addEventListener("load", apply);
        };

        // existing iframes
        document.querySelectorAll("iframe").forEach((iframe) => {
            handleIframe(iframe as HTMLIFrameElement);
        });

        // future iframes
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node instanceof HTMLIFrameElement) {
                        handleIframe(node);
                    }

                    if (node instanceof HTMLElement) {
                        node.querySelectorAll("iframe").forEach((iframe) => {
                            handleIframe(iframe as HTMLIFrameElement);
                        });
                    }
                });
            });
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
        });

        return () => {
            observer.disconnect();
            branding?.remove();
        };
    }, []);

I was try, but still not remove tawk branding

@hazelcorp2011-cmd

Copy link
Copy Markdown

Anyone can help me for removing tawk chat branding with plan JS Code.

@smlaticc

Copy link
Copy Markdown

Removed branding and also 2 items from dropdown menu.
Tested on tawk.to plugin for wordpress.
Works on mobile also.
Here:

var removeBranding = function () {

  var iframes = document.querySelectorAll("iframe");

  iframes.forEach(function (ifr, idx) {

    try {
      var doc = ifr.contentDocument || (ifr.contentWindow && ifr.contentWindow.document);      
      if (!doc) return;

      var btn = doc.querySelector('a[class*="tawk-button-small"]');
      if (btn) {
        btn.remove();
      }

      var popoutIcon = doc.querySelector("i.tawk-icon.tawk-icon-popout");
      if (popoutIcon) {
        var popoutButton = popoutIcon.closest("button");
        if (popoutButton) {
          popoutButton.remove();
        }
      }

      var byHref = doc.querySelector('a[href*="tawk.to/?utm_source=tawk-messenger"], a[href*="tawk.to/?utm_"]');
      if (byHref) {
        console.log("Removed by href:", byHref);
        byHref.remove();
        return;
      }

      var svgBranding = doc.querySelector('a svg[viewBox="0 0 107 15"]');
      if (svgBranding) {
        var brandingLink = svgBranding.closest("a");
        if (brandingLink) {
          console.log("Removed SVG branding:", brandingLink);
          brandingLink.remove();
          return;
        }
      }

      var nodes = Array.from(doc.querySelectorAll("a, div, span"));
      var poweredBy = nodes.find(function (el) {
        return normalizeText(el.textContent).includes("powered by tawk.to");
      });

      if (poweredBy) {
        console.log("Removed powered by text:", poweredBy);
        var a = poweredBy.tagName === "A" ? poweredBy : poweredBy.querySelector("a");
        (a || poweredBy).remove();
      }
    } 
    catch (e) {

    }
  });
};
setInterval(removeBranding, 250);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment