Go

Route Go's net/http client through NyxonProxies: http.ProxyURL with credentials, rotation, sticky sessions, SOCKS5, environment variables and errors.

Go's standard library handles authenticated proxies on its own. Put the credentials in the proxy URL, hand it to the transport, and net/http sends them to the gateway for every connection.

Basic request

go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

func main() {
	proxyURL, err := url.Parse("http://USERNAME:[email protected]:8080")
	if err != nil {
		panic(err)
	}
	client := &http.Client{
		Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
		Timeout:   30 * time.Second,
	}

	resp, err := client.Get("https://api.ipify.org")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}

The proxy URL starts with http:// even for HTTPS sites. The transport opens a tunnel through the gateway and runs TLS to the site inside it. Create the client once and reuse it.

A new IP on every request

The transport keeps connections open and reuses them, so requests to the same site share one IP. Turn keep-alives off and every request opens a new connection, which gets a new IP on a rotating username:

go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

func main() {
	proxyURL, _ := url.Parse("http://USERNAME:[email protected]:8080")
	client := &http.Client{
		Transport: &http.Transport{
			Proxy:             http.ProxyURL(proxyURL),
			DisableKeepAlives: true,
		},
		Timeout: 30 * time.Second,
	}

	for i := 0; i < 3; i++ {
		resp, err := client.Get("https://api.ipify.org")
		if err != nil {
			panic(err)
		}
		body, _ := io.ReadAll(resp.Body)
		resp.Body.Close()
		fmt.Println(string(body))
	}
}

Country and sticky session

Targeting and sessions go in the username. Build the URL with url.UserPassword, which also takes care of special characters in the password:

go
package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

func stickyClient(country string, minutes int) *http.Client {
	b := make([]byte, 4)
	rand.Read(b)
	user := fmt.Sprintf("USERNAME-country-%s-session-%s-time-%d", country, hex.EncodeToString(b), minutes)
	proxyURL := &url.URL{
		Scheme: "http",
		User:   url.UserPassword(user, "PASSWORD"),
		Host:   "geo.gw.nyxon.sh:8080",
	}
	return &http.Client{
		Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
		Timeout:   30 * time.Second,
	}
}

func main() {
	client := stickyClient("de", 10)
	for i := 0; i < 2; i++ {
		resp, err := client.Get("https://api.ipify.org")
		if err != nil {
			panic(err)
		}
		body, _ := io.ReadAll(resp.Body)
		resp.Body.Close()
		fmt.Println(string(body))
	}
}

Both requests print the same German IP for up to 10 minutes. See Rotating and sticky sessions.

SOCKS5

net/http supports SOCKS5 proxies too. Change the scheme and the port:

go
proxyURL, _ := url.Parse("socks5://USERNAME:[email protected]:1080")
client := &http.Client{
	Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
	Timeout:   30 * time.Second,
}

Go sends the hostname to the gateway, so DNS is resolved on the proxy side.

Environment variables

Go's default client, http.DefaultClient, reads HTTPS_PROXY, HTTP_PROXY and NO_PROXY. A transport you create yourself uses them when you set Proxy: http.ProxyFromEnvironment. Go never sends localhost or loopback addresses through a proxy. See Environment variables.

Errors

ErrorCause
Proxy Authentication RequiredWrong username or password, on an HTTPS site.
A response with status 407The same mistake on a plain http:// site. Check resp.StatusCode.
proxyconnect tcp: followed by a dial errorWrong host or port, or a firewall.
parse ...: invalid port ... after host from url.ParseSpecial characters in the password. Build the URL with url.UserPassword.

More in Error codes and Troubleshooting.

Last updated

Still stuck?

People answer the live chat around the clock. Send the proxy line you used (without the password) and the error you see.