A Website That Browses on Your Behalf#
A web proxy is a website with a URL box. You paste an address, the proxy's server fetches that page itself, rewrites the links inside it so they point back through the proxy, and serves you the result. Nothing is installed and no browser or system setting changes; the whole exchange is an ordinary visit to the proxy's own site. Older documentation calls the same idea a CGI proxy, and consumer services often market it as an “anonymizer” or “free web proxy.”
That deployment model is the defining difference from the proxies covered in the rest of this cluster. A configured proxy server is an address your client software is told to use, and it relays connections; a web proxy is a destination you browse to, and it fetches documents. The distinction sounds small and changes almost everything: who opens the connection to the destination, where TLS ends, which security boundaries the browser applies, and why pages break.
| Question | Web proxy (this page) | Configured proxy server | VPN |
|---|---|---|---|
| How you use it | Visit a website, paste a URL | Set it in an application, script, or OS policy | Install a client or profile at the OS layer |
| What it carries | Pages its rewriter understands, one document at a time | Connections from every application configured to use it | Normally all traffic from the device or tunnel scope |
| Who contacts the destination | The proxy's web server, with its own HTTP client | The proxy service, relaying your client's connection | Your applications, through an encrypted network path |
| Where TLS to the destination ends | At the proxy site, by design | At your client when tunneled with CONNECT | At your client |
| Typical failure | Rewriting misses a URL and the page breaks | Misconfigured client, DNS, or authentication | Routing, DNS, or kill-switch policy |
Like every intermediary, a web proxy changes the route a request takes. It does not grant permission to reach anything, it does not make you anonymous to the operator in the middle, and whether it may be used at all is governed by the network you are on and the destination's terms.
One Page Load, Two HTTP Conversations#
When you browse through a web proxy there are two separate HTTP conversations. The first is between your browser and the proxy site: a normal HTTPS website visit, carrying your cookies for that site, your user agent, and the target URL as a query parameter. The second is between the proxy's server and the destination: a fresh request made by the proxy's own HTTP client, from the proxy's network address, with whatever headers the operator's software chooses to send.
In the lab this guide is built on, the client requested the page with User-Agent: lab-client/1.0 and a cookie named client-secret. The origin's log recorded something else entirely:
[origin] GET / ua=webproxy-lab/1.0 cookie=noneThe visitor's user agent and cookie never crossed. That is not a privacy promise, it is an implementation detail: the proxy simply did not copy them. A different operator could forward your user agent, your language headers, or an X-Forwarded-For field naming your address, and from the outside you cannot verify which choice was made. The destination, meanwhile, sees the proxy's exit address as the network peer for the fetch, which is the one property web proxies are usually used for.
Keep the two-conversation picture in mind for the rest of this guide. Every capability and every failure of a web proxy comes from the same fact: your browser never talks to the destination. Something in the middle reads the page first, and everything you see afterward is its retelling.
URL Rewriting Is the Entire Mechanism#
Fetching one document is easy. The hard part is what happens next: every link, form, image, stylesheet, and script reference inside that document still points at the destination. If the proxy served the page unchanged, your very next click would leave the proxy and connect directly. So the proxy parses the HTML and rewrites addressing attributes to point back into itself. In the lab, the origin's page contained an absolute link, a relative link, a form, and an image; the proxied copy came back with all four rewritten:
<!-- served by the origin -->
<a href="/docs">Relative link</a>
<!-- served by the web proxy -->
<a href="/browse?url=http%3A%2F%2F127.0.0.1%3A8091%2Fdocs">Relative link</a>Following the rewritten link keeps the session inside the proxy: the lab's second origin request, for /pricing, again arrived from the proxy's client rather than the visitor's browser. Navigation only stays proxied because the rewriter caught the URL.
Cookies need the same treatment. Under RFC 6265, a cookie belongs to the site the browser actually talked to, and the browser talked to the proxy. A destination's Set-Cookie: session=origin-value cannot live on its own origin any more, so the lab proxy re-namespaced it before passing it on:
Set-Cookie: wp__127.0.0.1_8091__session=origin-value; Path=/; HttpOnlyEvery site you visit through one web proxy shares that proxy's cookie space, separated only as well as the operator's namespacing discipline. Your logged-in sessions, if you create any, are stored by and addressable to the proxy site, not to the services they belong to.
Run the Lab: a 40-Line Web Proxy on Loopback#
The fastest way to understand a web proxy is to run one against a page you control. This miniature version binds only to 127.0.0.1, refuses every destination except its own lab origin, and uses the built-in Node.js http module. It was written and verified with Node v24.14.0; save it as web-proxy-lab.mjs and do not point it at third-party sites.
// web-proxy-lab.mjs: a deliberately minimal URL-rewriting web proxy.
// Loopback only. Point it at nothing except the lab origin.
import http from 'node:http';
const ORIGIN = 'http://127.0.0.1:8091';
http.createServer((request, response) => {
console.log(`[origin] ${request.method} ${request.url}`,
`ua=${request.headers['user-agent']}`,
`cookie=${request.headers.cookie ?? 'none'}`);
response.setHeader('Set-Cookie', 'session=origin-value; Path=/');
response.setHeader('Content-Type', 'text/html; charset=utf-8');
response.end(`<h1>Origin ${request.url}</h1>
<a href="/docs">Relative link</a>
<script>fetch('/api' + '/quote').catch(() => {});</script>`);
}).listen(8091, '127.0.0.1');
http.createServer(async (request, response) => {
const url = new URL(request.url, 'http://127.0.0.1:8090');
const target = url.searchParams.get('url');
if (url.pathname !== '/browse' || !target || !target.startsWith(ORIGIN)) {
response.statusCode = 403;
return response.end('this lab proxy only serves the lab origin');
}
const upstream = await fetch(target, { headers: { 'user-agent': 'webproxy-lab/1.0' } });
const html = (await upstream.text()).replace(
/(href|src|action)="([^"]+)"/g,
(_, attr, value) => `${attr}="/browse?url=${encodeURIComponent(new URL(value, target).href)}"`,
);
const cookie = upstream.headers.get('set-cookie');
if (cookie) response.setHeader('Set-Cookie', `wp__origin__${cookie}`);
response.setHeader('Content-Type', 'text/html; charset=utf-8');
response.end(html);
}).listen(8090, '127.0.0.1', () => {
console.log('browse: http://127.0.0.1:8090/browse?url=' + encodeURIComponent(ORIGIN + '/'));
});Start it with node web-proxy-lab.mjs, then request the origin through the proxy from a second terminal, posing as a client with a secret cookie:
curl -s -i -A "lab-client/1.0" -b "client-secret=1" \
"http://127.0.0.1:8090/browse?url=http%3A%2F%2F127.0.0.1%3A8091%2F"Three observations to verify against your own run: the origin's console line shows ua=webproxy-lab/1.0 cookie=none, so nothing identifying the client crossed; the response HTML has the link rewritten onto /browse?url=; and the response's Set-Cookie arrives renamed with the wp__origin__ prefix. Then look at what was not rewritten, because that is the next section.
Why Modern Sites Break Inside One#
The lab origin's page ends with a script that assembles its request target at runtime: fetch('/api' + '/quote'). The proxied copy of the page contains that script byte for byte, unrewritten. The rewriter never had a chance: the string /api/quote does not exist in the document, it is created inside a JavaScript engine after delivery. When the browser runs it, the request goes to the proxy's origin, where no such API exists, or to wherever an absolute runtime URL points, escaping the proxy entirely.
That is the structural blind spot, and modern sites are built almost entirely inside it. Single-page applications construct API endpoints from configuration, bundlers emit dynamic imports, and scripts fetch JSON, media segments, and further scripts from URLs that only exist at runtime. A production rewriter can try to intercept more surfaces than the lab's regex does, and the serious ones inject client-side shims that patch browser APIs, but each uncovered channel is a broken feature: a login that loops, a search box that does nothing, a video that never starts, an upload that dies.
The browser's own security model adds a second layer of breakage. Under the same-origin policy, storage, script access, and service workers are partitioned by the origin the browser sees, and through a web proxy that origin is the proxy site, for every destination at once. Sites that depend on origin-scoped state (local storage, IndexedDB, workers, OAuth redirect flows that compare origins) are running under an identity they were not written for. WebSocket, streaming, and upload endpoints each need their own dedicated relay support in the proxy, so whether they work at all varies by implementation. None of this is fixable by the visitor; it is the cost of the retelling.
The Operator Terminates TLS by Design#
The padlock you see while using a web proxy describes your connection to the proxy site. Under TLS 1.3, the server that is authenticated is the one you connected to, and that is the proxy. When the destination is an HTTPS site, the proxy's server opens its own separate TLS session to fetch the page. Between those two encrypted legs, inside the operator's process, the content exists as plaintext; that is precisely where the rewriting from earlier sections happens. The lab's proxy recorded handling the origin's full page body on every fetch, because it had to read it to rewrite it.
This is not an accusation about any particular service; it is the architecture. Whoever operates a web proxy is positioned to read every page you view through it, every form value you submit, every credential you type, and every re-scoped session cookie it stores on your behalf, and to alter any of it in transit. Whether an operator logs, retains, sells, or injects into that stream is a policy you generally cannot audit from the outside.
Treat the decision like handing your browsing to a stranger's browser, because mechanically that is what it is. Before using one for anything beyond a disposable public page: identify who operates it, find a retention statement you actually believe, understand how a free service pays for its bandwidth, and never authenticate to another site through it. A configured proxy differs here in a specific, checkable way: when a client tunnels HTTPS with CONNECT, the intermediary relays encrypted bytes and your TLS session terminates at the destination. The configured proxy guide traces that boundary hop by hop.
When a Web Proxy Fits, and When It Cannot#
A web proxy is a reasonable tool for understanding intermediaries (the lab above exists for exactly that) and for a disposable, unauthenticated look at a public page when installing nothing matters more than fidelity, on a network whose rules permit it. It is the wrong tool for anything repeatable, authenticated, sensitive, or professional, and it grants no permission: destination terms and the policy of the network you are on continue to apply, and this guide does not cover routing around either. If a school, workplace, or platform restriction is the obstacle, the answer is authorization, not an intermediary.
For real work, pick the tool whose boundary matches the job. If an application needs a controlled network path with credentials, session control, and end-to-end TLS, use a configured proxy and verify the exit with the proxy checker before production traffic. If the goal is device-wide coverage rather than one application, the proxy versus VPN comparison walks the decision. If the question is whether a collection workflow is permitted at all, the risk-based compliance guide covers authorization, terms, and data duties before any traffic starts. And when the requirement is a maintained egress network with named accountability rather than an anonymous free site, that is what managed residential and datacenter networks are for.
The durable takeaway is the mechanism. A web proxy is a website that fetches on your behalf, rewrites what it can see, and retells the result from its own origin. Everything else (the convenience, the breakage, the operator's total visibility) follows from that one design.



