Run a headless browser through your own proxy server
A headless browser with a custom proxy is what you need when the exit IP is not yours to choose: a residential provider you already pay for, an address a partner has allow-listed, or a compliance rule about where traffic leaves from. Instead of launching and authenticating Chrome per proxy, pass the proxy URL with the request and the managed browser runs the page through it, credentials included.
Wiring an authenticated proxy into headless Chrome is fiddly
In Puppeteer the proxy is a launch flag, so it applies to the whole browser, and the username and password go in separately through page authentication on every page you open. Two proxies means two browsers. A second provider, a second country or a rotated credential means relaunching, and a mistake in any of those steps shows up as a timeout rather than a clear error.
Then the credential starts to travel. It ends up in environment files on every worker, in launch arguments that show in process lists, and sometimes in logs when a URL gets printed on failure. The proxy you pay for works, but the plumbing around it becomes its own small service to maintain.
With Microlink the proxy is a request option. proxy.url takes a standard URL with the credentials inside, and every sub-request made while resolving the page, from redirects to assets to dynamic fetches, goes through that server. The browser, the retries and the error codes stay on the API side, and a different proxy on the next call is just a different value.
How to use your own proxy with a headless browser API
Keep the proxy URL in an environment variable on your server and pass it per request. The proxy guide documents the format and the security rules in full.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const markdown = await microlink.markdown('https://example.com/article', {
proxy: { url: process.env.PROXY_URL }
})PROXY_URL holds a value such as https://username:password@hostname:port. The page, its redirects and every asset it loads leave through that server, and the call resolves to the Markdown of the page.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const text = await microlink.text('https://geolocation.microlink.io', {
proxy: process.env.PROXY_URL
})geolocation.microlink.io shows the IP and country the server sees, so the text should name your proxy’s exit, not a Microlink one. A bare string is shorthand for proxy.url.
curl -G https://pro.microlink.io \
--data-urlencode 'url=https://example.com/article' \
--data-urlencode "proxy.url=$PROXY_URL" \
-d meta=false \
-d screenshot=true \
-H "x-api-key: $MICROLINK_API_KEY"Both the proxy URL and the API key come from the shell environment, so neither is written into a script. Run it server-side only: the proxy URL is a credential.
- proxy.url Your proxy as a WHATWG URL, https://username:password@hostname:port. Pro plans.
- proxy Accepts an object or a bare string; a string is treated as proxy.url.
- retry Server-side retries with exponential backoff when your proxy is briefly unreachable. Default 2.
- timeout Maximum request time: 30 seconds on the free plan, 60 seconds on Pro.
If your proxy is flaky, the guide pairs it with retry: 3. For logged-in pages, the proxy only changes the exit IP; the session travels as forwarded request headers.
Why bring your own proxy to a managed browser
You keep the exit you trust and drop the browser fleet around it. The API owns everything between the proxy and the output.
The route shows in the x-fetch-mode response header, whose value ends in -proxy, as described in the proxy parameter reference.
If you do not need a specific provider, you may not need this at all: Pro plans already include a managed proxy, explained in the rotating proxy alternative.
When not to: for a country pin with no provider constraint, proxy.location is simpler. It is exclusive with proxy.url, so pick one per request.
FAQ
How do I use an authenticated proxy with a headless browser API?
Do redirects and assets also go through my own proxy?
Can I use my own proxy and pick a country at the same time?
Why do I get EINVALPROXY or EPROXY with my own proxy?
Is it safe to send proxy credentials to a scraping API?
Solve the next problem with the same API
Rotating proxy alternative
Fetch geo-blocked websites
Screenshot blocked websites
Ready to route through your own proxy?
Keep the provider you trust, drop the browser fleet. One option per request, on every product.