The Anti-Bot Technique: Cooperative Rendering with Blazeio

1 points by anonyxbiz 7 hours ago

The Discovery

While working with Blazeio (a Python async web framework with true zero-buffering streaming), I stumbled upon this technique - and it's so stupidly effective it feels like cheating.

The magic code: ``` import Blazeio as io import Blazeio.Other.proxy as proxy import Blazeio.Modules.onrender as onrender

io.INBOUND_CHUNK_SIZE, io.OUTBOUND_CHUNK_SIZE = 1024100, 1024100

io.Scope.add_imports(globals())

io.Scope.web = io.App("0.0.0.0", 9001, with_keepalive = 1)

class Element: __slots__ = ("r", "element", "className") def __init__(app, r: io.BlazeioProtocol, element: str, className: str = None): app.r, app.element, app.className = r, element.encode(), b'class="%b"' % className.encode() if className else b''

    async def __aenter__(app):
        await app.r.write(b'<%b %b>' % (app.element, app.className))
        return app

    async def __aexit__(app, *args):
        await app.r.write(b'</%b>' % app.element)
        return False

    async def text(app, text: str):
        return await app.r.write(text.encode())
class Dom: __slots__ = ("r", "event", "id") def __init__(app, r: io.BlazeioProtocol): app.r = r app.event = io.SharpEvent() app.id = io.token_urlsafe(11)

    async def __aenter__(app):
        await app.r.write(b'<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="UTF-8">\n<meta name="viewport" content="width=device-width, initial-scale=1.0">\n<title>Dynamic Rendering</title>\n<link rel="stylesheet" href="/get/favicon?id=%b" fetchpriority="high">\n</head>\n<body>\n' % app.id.encode())
        return app

    async def __aexit__(app, *args):
        await app.r.write(b'\n</body>\n</html>')
        return False
    
    def __await__(app):
        yield from app.event.wait_clear().__await__()
        return app
    
    def element(app, *args, **kwargs):
        return Element(app.r, *args, **kwargs)
@io.Scope.web.attach class Main: __slots__ = () events = io.ddict() def __init__(app): ...

    async def _get_favicon(app, r: io.BlazeioProtocol):
        if not (dom := app.events.pop(r.params().get("id"), None)): raise io.Abort("Not found", 404)
        dom.event.set()
        await io.Deliver.text("True")

    async def _(app, r: io.BlazeioProtocol):
        await r.prepare({"Content-type": "text/html", "Transfer-encoding": "chunked"}, 200)

        async with Dom(r) as dom:
            app.events[dom.id] = dom
            await dom

            async with dom.element("main") as element:
                await element.text("Hello world")
if __name__ == "__main__": with io.Scope.web: io.Scope.web.runner() ```

How It Works

For Real Browsers:

1. Browser requests / 2. Server streams: <!DOCTYPE...<link rel="stylesheet" href="/get/favicon?id=UNIQUE_ID"> 3. Browser naturally fetches the "stylesheet" (actually our trigger endpoint) 4. Server receives the trigger request and continues rendering: <main>Hello world</main> 5. User sees complete page

For Bots:

1. Bot requests / 2. Server streams: <!DOCTYPE...<link rel="stylesheet" href="/get/favicon?id=UNIQUE_ID"> 3. Bot doesn't fetch the "stylesheet" (or fetches it too late) 4. Server stops rendering at <body> 5. Bot sees incomplete page and gives up