Link copied to clipboard!
ProductsPricingUse CasesSolutionsResourcesCompanyFAQ
Get Started
Home Blog Proxies for AI Agents
Tutorials

Proxies for AI Agents: How to Connect Playwright, LangChain and n8n

Where a proxy belongs in an AI agent, and how to set it in Python, Playwright, a Playwright MCP server and n8n, with working code.

An AI agent that browses the web, reads documents or calls tools sends ordinary HTTP requests, and those requests leave from wherever your code runs. A proxy lets you choose that starting point: a country, a mobile carrier network or a server in a data center.

This guide shows where the proxy belongs in an agent, how to set it in Python, Playwright, a Playwright MCP server and n8n, how to keep one IP for one task and how to keep credentials out of prompts and logs. Every example uses placeholders and targets lawful, rate-limited access to public pages.

Key takeaways
  • Put the proxy on the tool that makes outbound requests: the HTTP client, the browser or the fetch step. Calls to the model API should not go through it.
  • Any framework that accepts a proxy URL or a Playwright proxy option works with Xameleon: HTTP(S) and SOCKS5, with a login and password.
  • Keep one IP for the whole task and change it between tasks, from your account or from your own code through the API.
  • Use mobile proxies when the carrier network matters, and datacenter proxies for server-side checks where it does not.
  • Credentials belong in environment variables or a secrets manager, never in prompts, tool descriptions or logs.
  • Traffic is paid per GB, so fetch text, cache results and cap the pages per task. Follow robots.txt, site terms and rate limits.

1.Why give an AI agent its own network path

An agent with web tools searches, opens pages, fills in forms in a headless browser and calls APIs. All of that is network traffic from your server, and three things about it matter once the agent does real work.

  • Location. Many pages change by country: language, prices, availability, legal notices. A cloud server sits in one place, so an agent that must read a page as a visitor from Ukraine or Germany needs a connection from there.
  • Consistency. A multi-step task, such as a login, a search with filters or a checkout review, goes better from one stable address than from a different one on every call.
  • Control. One proxy per agent or per task gives you a single place to count traffic, set limits and read logs, and it keeps network credentials apart from your code.

You do not always need a proxy. Public APIs, documentation sites and your own services work fine from your server. Add a proxy when the location or the type of network changes what the agent sees. Our page on proxies for AI agents and LLM tools lists the typical jobs, and web scraping proxies covers data collection in general.

2.Where the proxy goes in an agent

An agent is a loop: the model decides, a tool acts, the result goes back to the model. The proxy belongs to the tool side of that loop.

Model APIAgentTask logdirectToolProxyHTTP(S) or SOCKS5
The model API is called directly. Only the tool that fetches pages uses the proxy, and the task log records which country and proxy a run used.

Proxy the tool, not the model. Routing calls to the model provider through a proxy adds cost and one more thing that can fail, and it changes nothing about the pages the agent reads. In practice the proxy goes into one of these places:

  • an HTTP client inside a fetch or search function (Python requests or httpx, Node.js undici);
  • the launch options of a browser tool (Playwright, Puppeteer, Selenium);
  • the configuration of an MCP server that fetches or browses pages;
  • the proxy option of a workflow node, for example the HTTP Request node in n8n.

One trap: many HTTP libraries read the HTTP_PROXY and HTTPS_PROXY environment variables on their own, including the client inside a model provider’s SDK. If you export them for the whole process, your calls to the model go through the proxy as well. Set the proxy on the tool’s own client instead, or list the model host in NO_PROXY.

3.Mobile or datacenter proxies for agents

Both types work with every tool in this guide, and the choice depends on what the agent has to see and how long it works. What mobile proxies are and mobile versus datacenter proxies explain the difference in detail. For agents it comes down to this:

Question4G mobile proxiesDatacenter proxies
Where the IP comes fromA modem on a mobile carrier networkA server in a data center
How you payShared: per GB. Exclusive: a modem for a period, with traffic includedAn IP for a period, with traffic included
Fits agents thatcheck pages as visitors on a carrier network see them, or run longer, steadier sessionsfetch public pages and APIs where the type of network does not matter
Watch out forCellular links are slower than data centers and traffic costs more per GBPages that treat server addresses differently from carrier addresses
Change IPShared moves you to another modem in the same country; Exclusive restarts the modemYou get another server IP

Start with the cheaper option that gives the agent the right view, and measure the traffic of a real task before you scale. Both product pages show the countries you can order: 4G mobile proxies and datacenter proxies. Pricing lists the plans by country.

4.Check the proxy before you wire the agent

Test the proxy on its own first, so that a later failure can only come from the agent. Your account shows the host, the port, the login and the password. Replace the placeholders below and call our public IP endpoint, which returns the IP address and the country the server sees (up to 30 requests per minute per address, nothing is stored):

curl -x http://USERNAME:PASSWORD@HOST:PORT https://xameleon.cloud/api/tools/ip
# {"ip":"203.0.113.25","country":"UA"}

If the answer shows the carrier’s address and the country you ordered, the proxy works. The free proxy tools include an IP checker and a latency test for the same purpose. For a SOCKS5 test use --proxy socks5h:// with the same details.

5.One IP per task, a new IP between tasks

Task 1IP ATask 2IP BTask 3IP CChange IPChange IPthe same IP while the task runs
Each task keeps the IP it started with. The IP changes only in the gap between two tasks.

With Xameleon the IP is sticky: it stays the same while you work. There is no timer and no change on every request, so you decide when the address changes. Two details matter for agents:

  • Pauses. After a pause of about 10 minutes without connections, the next connection can get a different IP. An agent that waits for a human to approve a step should treat its next request as a fresh start.
  • Changing the IP. Press Change IP in your account, or call the API from your own code. A management API for proxies is described on the API page. Do it between tasks, not in the middle of one.

Log the IP and the country at the start of every task. When a run later looks wrong, you know which address it used. The guide on how to rotate proxies shows how to combine a sticky IP with several proxies in code.

6.A fetch tool for LangChain, LlamaIndex or your own loop

The simplest agent tool is a function that downloads a page and returns its text. Write it once with a proxy inside, and hand it to any framework. The proxy URL is built from environment variables, with the login and password percent-encoded:

import os
from urllib.parse import quote

import requests

def proxy_url() -> str:
    user = quote(os.environ["PROXY_USER"], safe="")
    password = quote(os.environ["PROXY_PASS"], safe="")
    return f"http://{user}:{password}@{os.environ['PROXY_HOST']}"    # PROXY_HOST is HOST:PORT

SESSION = requests.Session()
SESSION.proxies.update({"http": proxy_url(), "https": proxy_url()})
SESSION.headers["User-Agent"] = "my-agent/1.0 (contact: [email protected])"

def fetch_page(url: str) -> str:
    """Download a public web page and return its text (the first 20,000 characters)."""
    r = SESSION.get(url, timeout=(5, 20))
    r.raise_for_status()
    return r.text[:20000]

Both frameworks turn a plain function into a tool. The docstring becomes the description the model reads, so it describes the job and nothing else:

# LangChain
from langchain_core.tools import tool
fetch_tool = tool(fetch_page)

# LlamaIndex
from llama_index.core.tools import FunctionTool
fetch_tool = FunctionTool.from_defaults(fn=fetch_page)

Return text, not raw HTML: strip scripts, menus and footers before the page reaches the model, because every extra character costs tokens and traffic. If your agent stack is written in Node.js, undici gives the same result with a proxy agent:

import { ProxyAgent, fetch } from "undici";

const token = Buffer.from(`${process.env.PROXY_USER}:${process.env.PROXY_PASS}`).toString("base64");
const agent = new ProxyAgent({ uri: `http://${process.env.PROXY_HOST}`, token: `Basic ${token}` });

export async function fetchPage(url) {
  const res = await fetch(url, { dispatcher: agent, signal: AbortSignal.timeout(20000) });
  return (await res.text()).slice(0, 20000);
}

More Python options, including httpx, SOCKS5, timeouts and retries, are in the Python proxies guide.

7.Browser tools: Playwright and Playwright MCP

When a page needs JavaScript, an agent drives a real browser. Playwright takes the proxy in the launch options, with the login and password as separate fields:

import os
from playwright.sync_api import sync_playwright

PROXY = {
    "server": f"http://{os.environ['PROXY_HOST']}",    # HOST:PORT
    "username": os.environ["PROXY_USER"],
    "password": os.environ["PROXY_PASS"],
}

def read_page(url: str) -> str:
    """Open a public page in a browser and return the visible text."""
    with sync_playwright() as p:
        browser = p.chromium.launch(proxy=PROXY)
        page = browser.new_page()
        # skip images, media and fonts: they only cost traffic
        page.route("**/*", lambda route: route.abort()
                   if route.request.resource_type in {"image", "media", "font"} else route.continue_())
        page.goto(url, timeout=30000)
        text = page.inner_text("body")
        browser.close()
    return text[:20000]

In Node.js the same option is chromium.launch({ proxy: { server, username, password } }). Launch one browser per task, so the whole task shares one proxy and one IP. Chromium does not support SOCKS5 with a login and password in its proxy settings, so for browser tools use the HTTP(S) details from your account.

Playwright MCP

A Playwright MCP server lets an MCP client, such as an IDE or a desktop assistant, drive the browser. It reads its browser options from a configuration file. Point the MCP client at the file:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest", "--config", "/path/to/playwright-mcp.json"]
    }
  }
}

Then put the proxy into the launch options of that file:

{
  "browser": {
    "launchOptions": {
      "proxy": { "server": "http://HOST:PORT", "username": "USERNAME", "password": "PASSWORD" }
    }
  }
}

Keep that file outside your repository and readable only by you, because it holds the password. Option names change between releases, so check npx @playwright/mcp@latest --help and the project’s documentation for the version you run.

8.n8n workflows

In n8n the proxy is a setting of the node that makes the request. The steps for the HTTP Request node:

  1. Open the node, choose Add option and then Proxy.
  2. Enter http://USERNAME:PASSWORD@HOST:PORT, ideally from an environment variable or a credential rather than typed into the workflow.
  3. Point a test request at https://xameleon.cloud/api/tools/ip and check the address and country in the output.
  4. Add the real request, with a timeout and the retry settings of the node.

A self-hosted n8n can also read HTTP_PROXY and HTTPS_PROXY for the whole instance, but those variables then apply to every node. On n8n Cloud you cannot set environment variables, so use the node option there; check the n8n documentation for your version. If HTTPS requests fail through an HTTP proxy, test the same URL with curl first, update n8n and look at the n8n community forum, where this case has been discussed.

For pages that need a browser, do not squeeze Playwright into a workflow node. Run the read_page function from the previous section as a small service and call it from n8n over HTTP. The proxy stays in that service, and the workflow only passes URLs.

9.Keep credentials out of prompts, tool descriptions and logs

An agent talks a lot. Prompts, tool descriptions, tool results and error messages are sent to the model provider, written to traces and often stored. A proxy password that lands in any of them is no longer secret.

Where it leaksWhat to do
Prompts and tool descriptionsGive the model a function name and a docstring. The code reads the secret from the environment.
Tool arguments and resultsNever make the proxy a parameter the model can set or see. Return page text only.
Logs and tracesLog the task id, the country and the host. Redact ://user:pass@ before anything is written.
Repositories and screenshotsUse environment variables, a secrets manager or a file outside the repository.

A small redaction helper for logs:

import re

def redact(text: str) -> str:
    """Mask the login and password in any proxy URL inside a log line."""
    return re.sub(r"(://)[^/@\s]+@", r"\1***@", text)

If a password ever appears in a prompt or a log, change it in your account. The guide to secure and responsible proxy use covers credential care in more depth.

10.Budget the traffic and stay polite

An agent that is allowed to browse freely can load hundreds of pages for one question. Traffic is paid per GB, and other people’s servers pay for every request, so give each task a budget:

class Budget:
    def __init__(self, max_pages: int = 20, max_bytes: int = 2_000_000):
        self.max_pages, self.max_bytes = max_pages, max_bytes
        self.pages = self.bytes = 0

    def spend(self, size: int) -> None:
        self.pages += 1
        self.bytes += size
        if self.pages > self.max_pages or self.bytes > self.max_bytes:
            raise RuntimeError("task budget used up")
  • Cache. Store results by URL and do not fetch the same page twice in one run.
  • Limit concurrency. Run a few tasks in parallel per site, not dozens. For more parallel work, order more proxies instead of pushing one connection harder.
  • Slow down on errors. Back off when a site answers 429 or 5xx, and honor a Retry-After header.
  • Follow the rules of the site. Read robots.txt and the terms of use, send an honest User-Agent with a contact address and collect only what you may use.

Web scraping at scale goes deeper into request budgets and error handling, and the next articles in this series cover collecting data for AI training and RAG and checking AI search answers by country. Our Acceptable Use Policy lists what the service may not be used for.

11.Common mistakes

What goes wrongWhyFix
Calls to the model slow down or failHTTPS_PROXY is exported for the whole process, so the model SDK uses the proxySet the proxy on the tool’s client, or add the model host to NO_PROXY
The password shows up in a traceThe proxy URL was passed as a tool argument or printed in an errorRead it from the environment inside the tool and redact log lines
A multi-step task behaves oddlyThe IP was changed in the middle of the task, or a long pause let the session endChange the IP between tasks and keep pauses short
InvalidURL or authentication errorsSpecial characters in the login or password are not percent-encodedUse quote(value, safe="")
The agent hangsNo timeout on the request or the browserSet connect and read timeouts, and a time limit for the whole task
The traffic is used up quicklyThe agent loads full pages with images, or revisits the same pagesReturn text, skip heavy files, cache by URL and set a page budget
You cannot reproduce a runNothing recorded the country, the IP or the proxyLog them at the start of every task

12.FAQs

Do AI agents need proxies?

Not always. They help when the location or the network type changes what the agent sees, when a multi-step task needs one address for its whole length, or when you want one place to count and limit outbound traffic.

How do I add a proxy to a LangChain agent?

Put the proxy inside the tool that fetches pages, as in section 6, and give that function to LangChain with tool(fetch_page). The model client stays without a proxy.

Can Playwright use a SOCKS5 proxy with a login and password?

Chromium does not support SOCKS5 authentication in its proxy settings. Use the HTTP(S) details of your proxy for browser tools, and SOCKS5 for tools that support it, such as curl and Python with the SOCKS extra.

How many agents can share one proxy?

That depends on the traffic you use and on the rate limits of the sites you visit, not on a fixed number. Give every parallel task its own budget and delays. If you need more parallel work, order more proxies.

Can my agent change the IP by itself?

Yes, through the API, but do it from your orchestration code between tasks and not as a tool the model can call freely. See the API page for the endpoints.

Which proxy type is better for AI agents?

Use mobile proxies when the carrier network matters for what the agent reads, and datacenter proxies for server-side checks where it does not. Compare them in section 3.

Still have questions about mobile proxies? Visit our FAQ page for detailed answers, or contact our support team — we're here to help.

Proxies for AI agents: key takeaways and where to go next

Connecting proxies to AI agents comes down to a few dependable habits: proxy the tool and not the model, keep one IP for the length of a task, keep credentials out of prompts and logs, and give every task a traffic budget. With those in place the same setup works in a Python function, a Playwright browser, an MCP server and an n8n workflow.

Which proxies suit LLM tools?

Our 4G mobile proxies use carrier IPs and are billed per GB (Shared) or by period (Exclusive), and datacenter proxies use server IPs. Both accept HTTP(S) and SOCKS5 with a login and password, so no SDK is needed. Compare the options on the pricing page and read the overview of proxies for AI and LLM tools.

Where to go after the first working agent

Collect data responsibly with web scraping for AI training data and RAG, check how AI search answers differ in each market with AI search visibility by country, and manage proxies from code with the API.