Skip to content

Colly

Web & HTTPWeb AutomationGo

What it is

Colly is a fast web scraping framework for Go with callback-based parsing, automatic rate limiting, caching, cookie handling and parallel collectors.

A Collector visits URLs and fires callbacks on HTML elements matching CSS selectors. Limits control parallelism and delay per domain.

Installation

go get -u github.com/gocolly/colly/v2

Getting started

The smallest useful thing you can do with it, and what each part means.

Scrape with politeness limits
c := colly.NewCollector(
    colly.AllowedDomains("example.com"),
    colly.MaxDepth(2),
    colly.CacheDir("./cache"), // avoid re-fetching during development
)

c.Limit(&colly.LimitRule{
    DomainGlob:  "*",
    Parallelism: 2,
    Delay:       time.Second, // be a good citizen
})

c.OnHTML("a.book-link[href]", func(e *colly.HTMLElement) {
    e.Request.Visit(e.Attr("href")) // resolves relative URLs
})

c.OnHTML("h1.title", func(e *colly.HTMLElement) {
    fmt.Println(e.Text, e.Request.URL)
})

c.OnError(func(r *colly.Response, err error) {
    log.Printf("failed %s: %v", r.Request.URL, err)
})

c.Visit("https://example.com/books")
c.Wait()
The rate limit is not optional in practice — scraping without a delay gets you blocked and is rude. CacheDir makes iterating on selectors much faster.

Advanced usage

Where the library earns its place over a simpler alternative.

Structured extraction into a struct
type Book struct {
    Title  string `selector:"h1.title"`
    Author string `selector:".author"`
    Tags   []string `selector:".tag"`
}

c.OnHTML(".book-detail", func(e *colly.HTMLElement) {
    var book Book
    if err := e.Unmarshal(&book); err != nil {
        return
    }
    results = append(results, book)
})
Unmarshal maps selectors onto struct fields, which keeps extraction declarative instead of a pile of ChildText calls.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

Callbacks never fire
The domain is outside AllowedDomains, or the selector does not match. Print the response body to confirm what was actually returned.
Content is missing from the HTML
The page renders it with JavaScript. Colly only fetches HTML — use a headless browser such as chromedp instead.

Best practices

  • Always set a LimitRule with a delay — unthrottled scraping gets blocked and is antisocial.
  • Respect robots.txt and the site's terms; Colly can parse it for you.
  • Use CacheDir during development so you are not refetching on every run.
  • Set a descriptive UserAgent so site owners can identify and contact you.

Background

Why it exists, and what it was reacting to.

Colly gave Go an equivalent to Python's Scrapy: a scraper that handles concurrency, politeness and retries rather than leaving them to the caller.