Mobile Proxy for Go
Go's net/http client routes through a proxy when you set Transport.Proxy. For SOCKS5 you reach for golang.org/x/net/proxy. This guide wires both to a mobile proxy and triggers IP rotation against the switch API.
Prerequisites
- →Go 1.21+ installed (
go version). - →A mobile proxy slot, HTTP/SOCKS5 ports, username, password and API key from mobileproxies.org.
- →For SOCKS5:
go get golang.org/x/net/proxy.
Step-by-Step Configuration
Read credentials from the environment
# .env or your shell — never hard-code secrets export MP_HOST=proxy.mobileproxies.org export MP_HTTP_PORT=8000 export MP_SOCKS_PORT=1080 export MP_USER=u_4a9c export MP_PASS=p_2X7q export MP_API_KEY=YOUR_API_KEY export MP_SLOT=us-mob-01
HTTP proxy with net/http
package main
import (
"fmt"
"net/http"
"net/url"
"os"
"time"
)
// httpProxyClient builds an *http.Client that tunnels every request
// through the authenticated mobile proxy.
func httpProxyClient() (*http.Client, error) {
proxyURL, err := url.Parse(fmt.Sprintf(
"http://%s:%s@%s:%s",
url.QueryEscape(os.Getenv("MP_USER")),
url.QueryEscape(os.Getenv("MP_PASS")),
os.Getenv("MP_HOST"),
os.Getenv("MP_HTTP_PORT"),
))
if err != nil {
return nil, err
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyURL),
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
TLSHandshakeTimeout: 15 * time.Second,
}
return &http.Client{
Transport: transport,
Timeout: 30 * time.Second,
}, nil
}SOCKS5 proxy with golang.org/x/net/proxy
package main
import (
"context"
"net"
"net/http"
"os"
"time"
"golang.org/x/net/proxy"
)
// socks5ProxyClient routes traffic through the SOCKS5 port using an
// authenticated dialer wired into http.Transport.DialContext.
func socks5ProxyClient() (*http.Client, error) {
auth := &proxy.Auth{
User: os.Getenv("MP_USER"),
Password: os.Getenv("MP_PASS"),
}
addr := net.JoinHostPort(os.Getenv("MP_HOST"), os.Getenv("MP_SOCKS_PORT"))
dialer, err := proxy.SOCKS5("tcp", addr, auth, proxy.Direct)
if err != nil {
return nil, err
}
ctxDialer := dialer.(proxy.ContextDialer)
transport := &http.Transport{
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
return ctxDialer.DialContext(ctx, network, address)
},
}
return &http.Client{Transport: transport, Timeout: 30 * time.Second}, nil
}Make a request through the proxy
func main() {
client, err := httpProxyClient() // or socks5ProxyClient()
if err != nil {
panic(err)
}
resp, err := client.Get("https://example.com")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("status:", resp.Status)
}Verify It Works
Hit api.ipify.org through the client and print the egress IP. It should be a carrier-owned mobile IP, never your machine's real address.
func checkIP(client *http.Client) string {
resp, err := client.Get("https://api.ipify.org?format=text")
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return string(body) // e.g. 100.42.x.x on a mobile ASN
}Rotate the IP
Ask the carrier for a fresh IP with a POST to the switch endpoint. The request goes direct (not through the proxy) and authenticates with your API key:
func rotate() error {
url := fmt.Sprintf(
"https://buy.mobileproxies.org/api/v1/proxies/%s/switch",
os.Getenv("MP_SLOT"),
)
req, err := http.NewRequest(http.MethodPost, url, nil)
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("MP_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
return fmt.Errorf("switch failed: %s", resp.Status)
}
time.Sleep(4 * time.Second) // let the new IP bind
return nil
}Troubleshooting
"Proxy Authentication Required" (407)
The credentials never reached the proxy. Embed them in the url.Parse URL as user:pass@host, and url.QueryEscape any special characters in the password.
SOCKS5 panics on the type assertion
The proxy.ContextDialer assertion only works with recent golang.org/x/net. Run go get -u golang.org/x/net, or fall back to dialer.Dial inside a plain Dial field.
IP doesn't change after rotate()
Go reuses keep-alive connections. After a switch, call transport.CloseIdleConnections() so the next request opens a fresh tunnel on the new IP.
Related Guides
Developer Guide
HTTPX Proxy Setup in Python
proxy=, mounts, async, and SOCKS5
Developer Guide
Axios Proxy Setup in Node.js
Why the built-in proxy option breaks on HTTPS
Reference
SOCKS5 vs HTTP Proxy
Which port to use for which Go client
Reference
IP Rotation Best Practices
When and how often to call switch
Reference
How Websites Detect Proxies
Why mobile ASNs pass where datacenters fail
Run Go Through Mobile IPs
$5 trial. Drop in the http.Transport, point it at a carrier IP, and rotate on the API.