Install
Go 1.24 or newer, inside a module. Colly v2 lives under the /v2 import path.
go mod init monkeycrawl
go get github.com/gocolly/colly/v2Rotating residential
SetProxy sets the proxy and DisableKeepAlives on the collector's transport, so every request opens a new tunnel through the residential gateway and leaves from a new address. AllowURLRevisit lets the loop fetch the same URL three times, and the timeout goes from Colly's default 10 seconds to 30, which suits a slow residential exit.
package main
import (
"fmt"
"log"
"time"
"github.com/gocolly/colly/v2"
)
func main() {
c := colly.NewCollector(colly.AllowURLRevisit())
c.SetRequestTimeout(30 * time.Second)
if err := c.SetProxy("http://USER:[email protected]:8000"); err != nil {
log.Fatal(err)
}
c.OnResponse(func(r *colly.Response) {
fmt.Print(string(r.Body))
})
c.OnError(func(r *colly.Response, err error) {
log.Println(r.Request.URL, err)
})
for i := 0; i < 3; i++ {
c.Visit("https://httpbin.org/ip")
}
}A static datacenter or ISP IP
On a static datacenter IP you want the opposite: connections that stay open and get reused. SetProxy would switch keep-alives off again, so hand the collector a transport of your own with WithTransport, the proxy on it, and do not call SetProxy afterwards. This one crawls with up to eight requests in flight. For an ISP order, use the host and port your dashboard lists for it.
package main
import (
"log"
"net/http"
"net/url"
"time"
"github.com/gocolly/colly/v2"
)
func main() {
proxy, err := url.Parse("http://USER:PASS@IP:PORT")
if err != nil {
log.Fatal(err)
}
c := colly.NewCollector(colly.Async(true))
c.WithTransport(&http.Transport{
Proxy: http.ProxyURL(proxy),
MaxIdleConnsPerHost: 8,
})
c.SetRequestTimeout(30 * time.Second)
c.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 8})
c.OnResponse(func(r *colly.Response) {
log.Println(r.StatusCode, r.Request.URL)
})
for _, u := range []string{"https://httpbin.org/ip", "https://httpbin.org/headers"} {
c.Visit(u)
}
c.Wait()
}Keeping one identity
Each collector from NewCollector has its own in-memory cookie jar, shared by every Visit on it. With SetProxy on the rotating gateway, keep-alives are off, so those cookies arrive from a new address on every request, which a site that ties a session to an IP will notice. For one identity per collector, create each with NewCollector and give it a static IP or a residential sticky session; the session setting for your account is in the dashboard. Clone() is not a new identity: a clone shares the original's cookie jar and transport, proxy included.