# Using proxy servers

You will create a new profile with a SOCKS5 proxy, change it to an HTTP proxy, then remove the proxy entirely. The flow is identical across all SDKs; code samples are provided for Python, JavaScript, and C#.

# Prerequisites

  • Completion of the Quickstart guide
  • Kameleo app is running locally (default API base URL: http://localhost:5050).
  • Network access to the local API port (no firewall blocking 5050).
  • Access to at least one working proxy server (HTTP, HTTPS, SOCKS5, or SSH) with host, port, and credentials if required.

# 1. Create a profile with a proxy

Select a fingerprint and attach a proxy at creation. Provide credentials only when required by your provider.

from kameleo.local_api_client.models import CreateProfileRequest, ProxyChoice, Server

fps = client.fingerprint.search_fingerprints(device_type='desktop', browser_product='chrome')
profile = client.profile.create_profile(CreateProfileRequest(
    fingerprint_id=fps[0].id,
    name='proxy tutorial',
    proxy=ProxyChoice(
        value='socks5',
        extra=Server(host='1.2.3.4', port=1080, id='user', secret='pass')
    )
))
print('Created profile with proxy:', profile.id, profile.proxy.value)
// Assumes you created a local API client instance named `client`.
const fps = await client.fingerprint.searchFingerprints({ deviceType: "desktop", browserProduct: "chrome" }); // Fetch a Chrome desktop fingerprint
const profile = await client.profile.createProfile({
    fingerprintId: fps[0].id,
    name: "proxy tutorial",
    // ProxyChoice shape: { value: '<type>', extra: { host, port, id?, secret? } }
    proxy: {
        value: "socks5",
        extra: { host: "1.2.3.4", port: 1080, id: "user", secret: "pass" },
    },
});
console.log("Created profile with proxy", profile.id, profile.proxy?.value);
using Kameleo.LocalApiClient;
using Kameleo.LocalApiClient.Model;

// Assumes you created a local API client instance named `client`.
var fps = client.Fingerprint.SearchFingerprints(deviceType: "desktop", browserProduct: "chrome"); // Fetch a Chrome desktop fingerprint

var create = new CreateProfileRequest(
    fingerprintId: fps[0].Id,
    name: "proxy tutorial",
    proxy: new ProxyChoice(value: ProxyConnectionType.Socks5, extra: new Server(host: "1.2.3.4", port: 1080, id: "user", secret: "pass"))
);
var profile = client.Profile.CreateProfile(create);
Console.WriteLine($"Created profile {profile.Id} with proxy {profile.Proxy?.Value}");

Kameleo tests the proxy before launching the profile. If the test fails, the browser does not start.

# 2. Update the proxy

Stop the profile before changing proxy settings (rotation mid-session can cause network anomalies and is not supported).

client.profile.stop_profile(profile.id)
updated = client.profile.update_profile(profile.id, update_profile_request={
    'proxy': ProxyChoice(value='http', extra=Server(host='proxy.host', port=8000))
})
print('Updated proxy to', updated.proxy.value)
await client.profile.stopProfile(profile.id);
const updated = await client.profile.updateProfile(profile.id, {
    proxy: {
        value: "http",
        extra: { host: "proxy.host", port: 8000 },
    },
});
console.log("Updated proxy to", updated.proxy?.value);
client.Profile.StopProfile(profile.Id);
var update = new UpdateProfileRequest(proxy: new ProxyChoice(
    value: ProxyConnectionType.Http,
    extra: new Server(host: "proxy.host", port: 8000)
));
var updated = client.Profile.UpdateProfile(profile.Id, update);
Console.WriteLine($"Updated proxy to {updated.Proxy?.Value}");

# 3. Remove the proxy

Set the proxy to null (or omit the field) to revert to a direct connection.

removed = client.profile.update_profile(profile.id, update_profile_request={ 'proxy': None })
print('Proxy removed, value now:', removed.proxy)
const removed = await client.profile.updateProfile(profile.id, { proxy: null });
console.log("Proxy removed, now:", removed.proxy);
var removed = client.Profile.UpdateProfile(profile.Id, new UpdateProfileRequest(proxy: null));
Console.WriteLine($"Proxy removed: {(removed.Proxy == null ? "yes" : "no")}");

# 4. Configure proxy bypass (optional)

Some destinations do not need to go through your proxy. Bypassing them reduces proxy bandwidth usage and lowers costs. Common candidates include CDN hosts serving static assets (images, fonts, scripts), video streaming domains, and internal services. Configure a bypass list so those hosts connect directly while the rest of the traffic uses the proxy.

Kameleo automatically adds its own loopback endpoints. You only provide the additional hosts or CIDR ranges. The mechanism differs per browser engine:

  • Chroma: supply an extra command-line switch proxy-bypass-list with a semicolon-separated list.
  • Junglefox: set the preference network.proxy.no_proxies_on with a comma-separated list.

# Chroma example

from kameleo.local_api_client.models import BrowserSettings

client.profile.start_profile(profile_id, BrowserSettings(
    arguments=[
        'proxy-bypass-list=*.internal.local;192.168.0.0/16'
    ]
))
await client.profile.startProfile(profile.id, {
    arguments: ["proxy-bypass-list=*.internal.local;192.168.0.0/16"],
});
await client.Profile.StartProfileAsync(profile.Id, new BrowserSettings
{
    Arguments = ["proxy-bypass-list=*.internal.local;192.168.0.0/16"]
});

# Junglefox example

from kameleo.local_api_client.models import BrowserSettings, Preference

client.profile.start_profile(profile_id, BrowserSettings(
    preferences=[
        Preference(key='network.proxy.no_proxies_on', value='intranet.local,cdn.example.com:443')
    ]
))
await client.profile.startProfile(profile.id, {
    preferences: [{ key: "network.proxy.no_proxies_on", value: "intranet.local,cdn.example.com:443" }],
});
await client.Profile.StartProfileAsync(profile.Id, new BrowserSettings
{
    Preferences = [new("network.proxy.no_proxies_on", "intranet.local,cdn.example.com:443")]
});

Guidelines:

  • Keep the list minimal; every pattern incurs a small matching cost.
  • Use CIDR for subnets instead of enumerating many hosts.
  • Avoid bypassing domains that perform geo or security checks; you may expose differing IP behavior.
  • Remember that bypass applies to all schemes (HTTP/HTTPS/WebSocket) for those hosts.

# 5. Limit WebRTC to proxied TCP (optional)

Kameleo automatically masks your WebRTC IP address to match your proxy IP. However, WebRTC can still leak your real IP through non-proxied UDP connections because browsers do not route UDP traffic through HTTP/SOCKS proxies by default, and some proxy providers do not support UDP traffic at all.

To prevent IP leaks, configure the browser to only allow WebRTC connections over TCP that go through your proxy. The mechanism differs per browser engine:

  • Chroma: set the preference webrtc.ip_handling_policy to disable_non_proxied_udp.
  • Junglefox: set the preference media.peerconnection.ice.proxy_only to true.

# Chroma example

from kameleo.local_api_client.models import BrowserSettings, Preference

client.profile.start_profile(profile.id, BrowserSettings(
    preferences=[
        Preference(key="webrtc.ip_handling_policy", value="disable_non_proxied_udp")
    ]
))
await client.profile.startProfile(profile.id, {
    preferences: [{ key: "webrtc.ip_handling_policy", value: "disable_non_proxied_udp" }],
});
await client.Profile.StartProfileAsync(profile.Id, new BrowserSettings
{
    Preferences = [new("webrtc.ip_handling_policy", "disable_non_proxied_udp")]
});

See more details: Chrome's WebRTC IP handling policy.

# Junglefox example

from kameleo.local_api_client.models import BrowserSettings, Preference

client.profile.start_profile(profile.id, BrowserSettings(
    preferences=[
        Preference(key="media.peerconnection.ice.proxy_only", value=True)
    ]
))
await client.profile.startProfile(profile.id, {
    preferences: [{ key: "media.peerconnection.ice.proxy_only", value: true }],
});
await client.Profile.StartProfileAsync(profile.Id, new BrowserSettings
{
    Preferences = [new("media.peerconnection.ice.proxy_only", true)]
});

# 6. Best practices

  • Match proxy country with fingerprint locale and language.
  • Rotate failing residential proxies; monitor connection error rate.
  • Keep a warm pool of tested proxies to reduce startup latency.
  • Avoid switching IP mid-session to prevent extra security or re-auth challenges.