Feature request: network-enforceable safe-content mode (dedicated "safe" hostname)

Member
Joined
Sep 13, 2026
Messages
3
I'd like to allow the site on my home network while blocking pornographic content network-wide.

Right now DNS filtering can't tell safe and explicit manga apart, since both are served from the same domain. That leaves network admins (like myself) with two bad options: block the whole site, or allow it with no restrictions.

Could you offer a network-enforceable safe-content mode, maybe through a dedicated hostname like safe.mangadex.com? This hostname would only serve content below a set rating threshold, with that restriction applied server-side across search, recommendations, listings, and API responses.

Admins could then permit the site at the DNS level while keeping explicit content off-limits for anyone on that network.
Families, schools, libraries, and other managed networks would all benefit from this.

Is this something you'd consider building?
 
Upvote 0
Womp Womp
Staff
Super Moderator
Joined
Aug 23, 2023
Messages
1,194
I'd like to allow the site on my home network while blocking pornographic content network-wide.

Right now DNS filtering can't tell safe and explicit manga apart, since both are served from the same domain. That leaves network admins (like myself) with two bad options: block the whole site, or allow it with no restrictions.

Could you offer a network-enforceable safe-content mode, maybe through a dedicated hostname like safe.mangadex.com? This hostname would only serve content below a set rating threshold, with that restriction applied server-side across search, recommendations, listings, and API responses.

Admins could then permit the site at the DNS level while keeping explicit content off-limits for anyone on that network.
Families, schools, libraries, and other managed networks would all benefit from this.

Is this something you'd consider building?
I doubt this will be implemented anytime soon, so as an alternative, here's a simple userscript that dynamically gets rid of the erotica and pornographic content ratings, so they're essentially filtered out regardless of the account's user settings:

JavaScript:
// ==UserScript==
// @name         Keep It Clean
// @namespace    https://mangadex.org/
// @version      1.0
// @description  For when you don't want your food "too spicy"
// @author       Bartolumiu
// @match        https://mangadex.org/*
// @match        https://canary.mangadex.dev/*
// @match        https://sandbox.mangadex.dev/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const cleanUrl = (inputUrl) => {
        if (typeof inputUrl !== 'string' || !inputUrl.includes('contentRating')) {
            return inputUrl;
        }

        try {
            const isRelative = !/^https?:\/\//i.test(inputUrl);
            const baseUrl = isRelative ? window.location.origin : undefined;
            const urlObj = new URL(inputUrl, baseUrl);

            if (urlObj.searchParams.has('contentRating[]')) {
                const ratings = urlObj.searchParams.getAll('contentRating[]');
                const filtered = ratings.filter(r => r !== 'erotica' && r !== 'pornographic');

                if (ratings.length !== filtered.length) {
                    urlObj.searchParams.delete('contentRating[]');
                    filtered.forEach(r => urlObj.searchParams.append('contentRating[]', r));

                    return isRelative ? urlObj.pathname + urlObj.search + urlObj.hash : urlObj.toString();
                }
            }
        } catch (e) {
            console.error('[Keep It Clean] Error parsing URL:', e);
        }

        return inputUrl;
    };

    const originalFetch = window.fetch;
    window.fetch = function(input, init) {
        let url;
        let isRequestObj = false;
        let isUrlObj = false;

        if (typeof input === 'string') {
            url = input;
        } else if (input instanceof Request) {
            url = input.url;
            isRequestObj = true;
        } else if (input instanceof URL) {
            url = input.toString();
            isUrlObj = true;
        }

        if (url) {
            const cleanedUrl = cleanUrl(url);
            if (cleanedUrl !== url) {
                if (isRequestObj) {
                    input = new Request(cleanedUrl, input);
                } else if (isUrlObj) {
                    input = new URL(cleanedUrl);
                } else {
                    input = cleanedUrl;
                }
            }
        }

        return originalFetch.call(this, input, init);
    };

    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url, ...rest) {
        if (typeof url === 'string') {
            url = cleanUrl(url);
        } else if (url instanceof URL) {
            url = new URL(cleanUrl(url.toString()));
        }
        return originalOpen.call(this, method, url, ...rest);
    };
})();

To add it, you'll need something like TamperMonkey: https://www.tampermonkey.net/
 
Member
Joined
Sep 13, 2026
Messages
3
I doubt this will be implemented anytime soon, so as an alternative, here's a simple userscript that dynamically gets rid of the erotica and pornographic content ratings, so they're essentially filtered out regardless of the account's user settings:

JavaScript:
// ==UserScript==
// @name         Keep It Clean
// @namespace    https://mangadex.org/
// @version      1.0
// @description  For when you don't want your food "too spicy"
// @author       Bartolumiu
// @match        https://mangadex.org/*
// @match        https://canary.mangadex.dev/*
// @match        https://sandbox.mangadex.dev/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const cleanUrl = (inputUrl) => {
        if (typeof inputUrl !== 'string' || !inputUrl.includes('contentRating')) {
            return inputUrl;
        }

        try {
            const isRelative = !/^https?:\/\//i.test(inputUrl);
            const baseUrl = isRelative ? window.location.origin : undefined;
            const urlObj = new URL(inputUrl, baseUrl);

            if (urlObj.searchParams.has('contentRating[]')) {
                const ratings = urlObj.searchParams.getAll('contentRating[]');
                const filtered = ratings.filter(r => r !== 'erotica' && r !== 'pornographic');

                if (ratings.length !== filtered.length) {
                    urlObj.searchParams.delete('contentRating[]');
                    filtered.forEach(r => urlObj.searchParams.append('contentRating[]', r));

                    return isRelative ? urlObj.pathname + urlObj.search + urlObj.hash : urlObj.toString();
                }
            }
        } catch (e) {
            console.error('[Keep It Clean] Error parsing URL:', e);
        }

        return inputUrl;
    };

    const originalFetch = window.fetch;
    window.fetch = function(input, init) {
        let url;
        let isRequestObj = false;
        let isUrlObj = false;

        if (typeof input === 'string') {
            url = input;
        } else if (input instanceof Request) {
            url = input.url;
            isRequestObj = true;
        } else if (input instanceof URL) {
            url = input.toString();
            isUrlObj = true;
        }

        if (url) {
            const cleanedUrl = cleanUrl(url);
            if (cleanedUrl !== url) {
                if (isRequestObj) {
                    input = new Request(cleanedUrl, input);
                } else if (isUrlObj) {
                    input = new URL(cleanedUrl);
                } else {
                    input = cleanedUrl;
                }
            }
        }

        return originalFetch.call(this, input, init);
    };

    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url, ...rest) {
        if (typeof url === 'string') {
            url = cleanUrl(url);
        } else if (url instanceof URL) {
            url = new URL(cleanUrl(url.toString()));
        }
        return originalOpen.call(this, method, url, ...rest);
    };
})();

To add it, you'll need something like TamperMonkey: https://www.tampermonkey.net/
thank you for the suggestion but I think you are missing the point.

the point of the feature that I am proposing is to enforce a safe mode on all the devices in the network in such a way that it can't be bypassed by the devices in any way short of a VPN or a proxy, two bypass methods that can be restricted too to some extent. a userscript or any client-side solution can be much easier to bypass by the client unless the client device is being administered with some kind of mobile device management which is not an option since we are talking about a home network not a corporate setting.

your proposed alternative is not actually an alternative at all the same way turning on Safe Search on a kid's phone doesn't substitute for parental controls enforced remotely.
 
Last edited:
Womp Womp
Staff
Super Moderator
Joined
Aug 23, 2023
Messages
1,194
thank you for the suggestion but I think you are missing the point.

the point of the feature that I am proposing is to enforce a safe mode on all the devices in the network in such a way that it can't be bypassed by the devices in any way short of a VPN or a proxy, two bypass methods that can be restricted too to some extent. a userscript or any client-side solution can be much easier to bypass by the client unless the client device is being administered with some kind of mobile device management which is not an option since we are talking about a home network not a corporate setting.

your proposed alternative is not actually an alternative at all the same way turning on Safe Search on a kid's phone doesn't substitute for parental controls enforced remotely.
I offered the userscript purely as an immediate band-aid because a true network-level solution isn't on the table for the foreseeable future.
I also understand that for a managed home network, a client-side script doesn't really solve the core issue since, as you already mentioned, anyone can just disable it of bypass it.

The issue is that implementing a network-enforceable safe mode is a massive architectural undertaking. Setting up a dedicated hostname like safe.mangadex.org is just adding a virtual host, and (agreeing with the internal comments from infra, since I forwarded this for consideration), DNS filtering alone is actually the wrong way to go about it for our setup.

To enforce this properly ,the backend would have to dynamically intercept the host header on every single API request and forcefully rewrite database queries (searches, feeds, recommendations, etc.) to exclude explicit content. On top of that, handling the image CDN and caching layers would be a nightmare. We would either have to split our entire caching infrastructure down the middle so safe-mode users don't accidentally get served cached unrestricted content, or we'd have to run heavy database lookups on every single static image request just to verify its content rating before serving it.

That said, if you're looking for a project and want total control over what gets served on your network, our API is completely public. You could theoretically build and host your own custom, stripped-down frontend on your local network that hardcodes the contentRating filters and only ever pulls safe content. If that's something you want to explore, you can find the API documentation here: https://api.mangadex.org/docs/

And sure, it's a pretty solid request that would definitely benefit families and schools, but the reality is that building and maintaining that separation on our end requires a massive amount of work across the entire stack for a very specific usecase. If we had unlimited resources we'd probably explore it, but that's sadly not the case, which is why I doubt we'll see it officially implemented anytime soon.
 
Member
Joined
Sep 13, 2026
Messages
3
I offered the userscript purely as an immediate band-aid because a true network-level solution isn't on the table for the foreseeable future.
I also understand that for a managed home network, a client-side script doesn't really solve the core issue since, as you already mentioned, anyone can just disable it of bypass it.

The issue is that implementing a network-enforceable safe mode is a massive architectural undertaking. Setting up a dedicated hostname like safe.mangadex.org is just adding a virtual host, and (agreeing with the internal comments from infra, since I forwarded this for consideration), DNS filtering alone is actually the wrong way to go about it for our setup.

To enforce this properly ,the backend would have to dynamically intercept the host header on every single API request and forcefully rewrite database queries (searches, feeds, recommendations, etc.) to exclude explicit content. On top of that, handling the image CDN and caching layers would be a nightmare. We would either have to split our entire caching infrastructure down the middle so safe-mode users don't accidentally get served cached unrestricted content, or we'd have to run heavy database lookups on every single static image request just to verify its content rating before serving it.

That said, if you're looking for a project and want total control over what gets served on your network, our API is completely public. You could theoretically build and host your own custom, stripped-down frontend on your local network that hardcodes the contentRating filters and only ever pulls safe content. If that's something you want to explore, you can find the API documentation here: https://api.mangadex.org/docs/

And sure, it's a pretty solid request that would definitely benefit families and schools, but the reality is that building and maintaining that separation on our end requires a massive amount of work across the entire stack for a very specific usecase. If we had unlimited resources we'd probably explore it, but that's sadly not the case, which is why I doubt we'll see it officially implemented anytime soon.
Thanks for making the situation crystal clear, I hope one day this happens and I think I will look into the API, it seems promising as a nice albeit stopgap solution.
 
Last edited:
Womp Womp
Staff
Super Moderator
Joined
Aug 23, 2023
Messages
1,194

Users who are viewing this thread

Top