Yes, Your Browser Can Run Its Own Tiny AI. Here’s How A browser extension can now run a small language model locally, with no server or API key, using either Chrome's built-in Gemini Nano or a custom model via Transformers.js on WebGPU. The approach enables on-device tasks like summarization and question-answering, with trade-offs between simplicity and control. A browser extension that reads the page you are on, answers questions about it, and summarizes it, with no server, no API key, and no data ever leaving your machine, isn’t a fantasy anymore. In 2026 it’s a weekend project. The trick is running a very small language model directly inside the browser, and there are now two solid ways to do it. This walks through both, the architecture that makes it work, the honest limits of tiny models, and a complete working extension you can load and use today. Here’s a fun question that turns out to have a genuinely interesting answer. Can your browser run its own AI, locally, with no cloud call behind it, and can you build that into a small extension. A year or two ago the honest answer was “not really, not usefully.” Today the answer is yes, and it’s not even that hard. The browser has quietly become a real place to run small language models, and a browser extension is one of the most natural homes for one, because it already has permission to see your tabs, read the page, and live in a side panel next to your reading. The key word is small. You’re not going to run a frontier model in a browser tab, and you shouldn’t try. But a small model, in the range of half a billion to a few billion parameters, quantized down to four bits, fits comfortably in browser memory and runs at usable speed on ordinary hardware. And for a lot of genuinely useful tasks, summarizing, rewriting, extracting, answering simple questions about the page in front of you, a small model is entirely enough. This piece explains the two ways to do it, shows the architecture, and gives you a complete working extension to build on. There are two distinct ways to put a small AI inside your browser in 2026, and they suit different goals. The first path is Chrome’s own built-in model. Chrome now ships a small model, Gemini Nano, baked directly into the browser, and extensions can call it through a built-in Prompt API with almost no code. You don’t ship a model, you don’t manage a download, you just ask the browser to run a prompt for you. Calling it looks about as simple as it gets, you create a session and prompt it. js const session = await self.ai.languageModel.create { systemPrompt: "You are a concise assistant.",} ;const result = await session.prompt "Summarize this in one sentence." ; That’s the whole thing. The model is already there, shared across every extension and page on the machine, running fully on-device and offline once available. The tradeoffs are that it’s English-only, it is not tuned for factual accuracy, its context window is small, and you can’t pin or choose the model version, it’s tied to Chrome’s update cycle and you get whatever ships. For a lot of extensions, none of that matters and the near-zero setup is worth everything. The second path is bringing your own model with a library called Transformers.js, from Hugging Face, running on WebGPU. Here you choose a specific small model, bundle the logic to load it, and it runs on the user’s GPU through the browser’s modern compute layer. This is more work and it means a one-time model download for the user, but it buys you control, you pick the exact model, you can choose a multilingual one, a code-focused one, or whatever fits, and the behavior doesn’t change out from under you when Chrome updates. This is the path to choose when you want a specific capability or predictable behavior, and it’s the one the working example below uses, because it teaches you more about how the whole thing fits together. The quick rule is this. If you want the simplest possible on-device AI and Chrome-only, English-only is fine, use the built-in Prompt API. If you want a specific model, cross-version stability, or capabilities the built-in model does not have, bring your own with Transformers.js. Both run entirely on the user’s machine, which is the whole point. Before the code, the shape of the thing, because there’s one design decision that matters more than any other and it trips up everyone who skips it. A small model is still hundreds of megabytes and its inference is heavy. If you load and run it in the same place as your user interface, the interface freezes solid every time the model thinks. So the golden rule of an in-browser-AI extension is that the model lives in the background service worker, not the UI. The background worker loads the model once, keeps it resident, and does all the generation. The side panel, the visible chat, holds no model at all. It just sends the worker a message like “generate an answer to this,” and the worker streams tokens back which the panel renders as they arrive. That gives you a clean three-part structure. The background service worker is the engine, it hosts the model and runs inference. The side panel is the face, it takes input and displays streamed output. And a content script is the reach into the page, it runs in the actual web page and extracts the readable text when asked, so the model has something to summarize or answer questions about. Messages flow between them, panel to worker to generate, content script to panel to fetch page text. Get that separation right and everything else is detail. Here is a complete, minimal extension that does something genuinely useful, it summarizes the page you’re on and answers questions about it, entirely locally. I’ll show the important pieces. The full set of files is packaged for download at the end. It starts with the manifest, which declares a Manifest V3 extension with the three parts, a background worker, a side panel, and a content script, plus permission to read the active tab. { "manifest version": 3, "name": "Pagewise, a tiny on-device AI", "version": "1.0.0", "permissions": "sidePanel", "activeTab", "scripting", "storage" , "host permissions": "