A lightweight Go toolkit for working with HTTP/SOCKS proxies. It provides three packages that work independently or together:
| Package | Purpose |
|---|---|
proxykit |
Core Proxy model with validation, getters, setters, and URL export |
proxyparser |
Parse custom proxy-format strings into Proxy structs |
proxypool |
Iterate over large proxy files without loading them into memory |
- Go 1.26 or later
go get -u github.com/colduction/proxykit-goThe proxykit.Proxy struct holds a scheme, a host:port pair, and optional credentials.
| Constant | Value |
|---|---|
proxykit.HTTP |
"http" |
proxykit.HTTPS |
"https" |
proxykit.SOCKS5 |
"socks5" |
proxykit.SOCKS5H |
"socks5h" |
package main
import (
"fmt"
"github.com/colduction/proxykit-go"
)
func main() {
p := &proxykit.Proxy{
Scheme: proxykit.HTTP,
Host: "example.com:8080",
Username: "user",
Password: "pass",
}
if p.IsValid() {
fmt.Println(p.ExportURL().String())
// Output: http://user:pass@example.com:8080
}
}| Method | Description |
|---|---|
IsValid() bool |
Returns true if scheme, host, and credentials are all valid |
IsZero() bool |
Returns true if the struct is its zero value |
IsCredentialFilled() bool |
Returns true if a username has been set |
ExportURL() *url.URL |
Returns the proxy as a *url.URL |
Reset() |
Clears all fields back to their zero values |
GetScheme() / SetScheme() |
Read or write the scheme |
GetHost() / SetHost() |
Read or write the host |
GetUsername() / SetUsername() |
Read or write the username (max 255 bytes) |
GetPassword() / SetPassword() |
Read or write the password (max 255 bytes) |
These package-level functions can be used without a Proxy instance:
proxykit.IsValidScheme("socks5") // true
proxykit.IsValidHostnamePort("example.com:8080") // true
proxykit.IsValidCredentials("user", "pass") // true| Function | Description |
|---|---|
IsValidScheme(s ProxyScheme) bool |
Checks that the scheme is one of the four supported values |
IsValidHostnamePort(s string) bool |
Validates host:port — port must be 1–65535, host must be RFC 1123 |
IsValidCredentials(username, password string) bool |
A non-empty password requires a username; both must be ≤255 printable ASCII bytes |
proxyparser.New compiles a format string into a reusable, goroutine-safe parser.
| Verb | Captures |
|---|---|
%t |
Scheme (e.g. http, socks5) |
%h |
Hostname |
%d |
Port |
%u |
Username |
%p |
Password |
%% |
Literal % character |
Any characters between verbs are treated as literal delimiters.
| Mode | Behavior |
|---|---|
strict = true |
Input must match the format exactly; any mismatch or trailing data returns an error |
strict = false |
Missing credentials (%u, %p) and trailing characters are tolerated as long as the scheme and host are parsed successfully |
package main
import (
"fmt"
"log"
"github.com/colduction/proxykit-go/proxyparser"
)
func main() {
// Standard format: scheme://host:port@username:password
parser, err := proxyparser.New("%t://%h:%d@%u:%p", true)
if err != nil {
log.Fatal(err)
}
proxy, err := parser.Parse("http://example.com:8080@user:pass")
if err != nil {
log.Fatal(err)
}
fmt.Println(proxy.ExportURL().String())
// Output: http://user:pass@example.com:8080
}Custom delimiters work too:
// Format: (scheme)host:port:username:password
parser, err := proxyparser.New("(%t)%h:%d:%u:%p", false)
proxy, err := parser.Parse("(http)res-us.example.net:9999:admin:pass")| Error Type | Meaning |
|---|---|
ErrInvalidFormatVerb |
Unknown verb character after % |
ErrInvalidFormatEndStr |
Format string ends with a bare % |
ErrMismatchDelim |
A literal delimiter in the format did not match at the given position |
ErrSubseqDelimNotFound |
A following delimiter was expected but not found |
ErrUnexpectedTrail |
Trailing characters in strict mode |
ErrInvalidProxyFormat |
The parsed result is not a valid proxy |
ErrHostNotParsed |
Host could not be extracted |
ErrSchemeNotParsed |
Scheme could not be extracted |
proxypool.New opens a proxy file and returns a ProxyPool that streams proxies without loading the whole file into RAM. It is safe for concurrent use from multiple goroutines.
| Constant | Behavior |
|---|---|
proxypool.ModeSequential |
Returns proxies in file order; no sidecar index is built |
proxypool.ModeShuffled |
Returns proxies in a random permuted order; builds a <file>.idx sidecar for O(1) seeks |
package main
import (
"fmt"
"log"
"github.com/colduction/proxykit-go/proxypool"
)
func main() {
// ModeShuffled — random order, cycle forever
pool, err := proxypool.New("proxies.txt", proxypool.ModeShuffled, true)
if err != nil {
log.Fatal(err)
}
defer pool.Close()
for proxy, ok := pool.Next(); ok; proxy, ok = pool.Next() {
fmt.Println(proxy)
}
}| Parameter | Type | Description |
|---|---|---|
path |
string |
Path to the newline-delimited proxy file |
mode |
proxypool.Mode |
ModeSequential or ModeShuffled |
reuse |
bool |
If true, iteration restarts from the beginning after the last proxy is returned |
When using ModeShuffled, a <path>.idx binary file is created next to the proxy file on the first run. Subsequent runs reuse it, making startup instant for large files. The index stores 8-byte offsets for every line, enabling O(1) random access.
type ProxyPool interface {
Next() (string, bool)
Close() error
}Next()returns the next proxy string. The boolean isfalsewhen the pool is exhausted (andreuseisfalse).Close()releases the open file handles and sidecar index.
package main
import (
"fmt"
"log"
"github.com/colduction/proxykit-go"
"github.com/colduction/proxykit-go/proxyparser"
"github.com/colduction/proxykit-go/proxypool"
)
func main() {
// 1. Build a parser for a custom proxy format
parser, err := proxyparser.New("%t://%h:%d@%u:%p", false)
if err != nil {
log.Fatal(err)
}
// 2. Parse a single proxy string
proxy, err := parser.Parse("http://proxy.example.com:8080@alice:secret")
if err != nil {
log.Fatal(err)
}
if proxy.IsValid() {
fmt.Println(proxy.ExportURL().String())
// http://alice:secret@proxy.example.com:8080
}
// 3. Stream proxies from a file
pool, err := proxypool.New("proxies.txt", proxypool.ModeSequential, false)
if err != nil {
log.Fatal(err)
}
defer pool.Close()
for line, ok := pool.Next(); ok; line, ok = pool.Next() {
p, err := parser.Parse(line)
if err != nil || !p.IsValid() {
continue
}
_ = proxykit.IsValidScheme(p.GetScheme())
fmt.Println(p.ExportURL().String())
}
}See LICENSE for details.