[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-es-rotacion-proxies-colly-golang-1":3},{"success":4,"payload":5,"related":62,"errors":126},true,{"id":6,"slug":7,"title":8,"excerpt":9,"body_html":10,"meta_title":11,"meta_description":12,"canonical_url":13,"canonical_override":14,"og_title":11,"og_description":12,"og_image_url":15,"faq_json":16,"key_takeaways":14,"allow_index":29,"noindex_google_only":29,"allow_follow":4,"published_at":30,"updated_at":30,"content_updated_at":31,"featured_image_url":32,"featured_image_alt":33,"card_image_url":34,"reading_time_minutes":35,"author":36,"categories":40,"tags":47,"alternates":48,"locale_paths":60,"views":61},175,"rotacion-proxies-colly-golang-1","Rotación de proxies en Colly: guía completa para scraping en Go","Aprende a integrar rotación de proxies residenciales en Colly con RoundRobinProxySwitcher, switchers personalizados y patrones de producción para scraping en Go.","\u003Cp>La rotación de proxies en Colly es la técnica fundamental para mantener un scraper en Go operativo cuando los sitios objetivo implementan rate limiting o bloqueos por IP. Colly, el framework de scraping más popular del ecosistema Go, ofrece puntos de extensión idiomáticos para integrar proxies residenciales sin acoplar tu lógica de negocio al transporte HTTP.\u003C\u002Fp>\n\n\u003Cblockquote>\u003Cp>\u003Cstrong>Aviso legal:\u003C\u002Fstrong> Este artículo cubre técnicas de scraping de datos públicos. En EE.UU., la \u003Ca href=\"https:\u002F\u002Fwww.law.cornell.edu\u002Fuscode\u002Ftext\u002F18\u002F1030\" rel=\"noopener noreferrer\">Computer Fraud and Abuse Act (CFAA)\u003C\u002Fa> prohíbe el acceso no autorizado a sistemas protegidos. En la UE, el \u003Ca href=\"https:\u002F\u002Fgdpr.eu\u002F\" rel=\"noopener noreferrer\">GDPR\u003C\u002Fa> regula el tratamiento de datos personales. Respeta el \u003Ccode>robots.txt\u003C\u002Fcode>, los términos de servicio y las leyes aplicables antes de scrape cualquier sitio.\u003C\u002Fp>\u003C\u002Fblockquote>\n\n\u003Ch2>Rotación de proxies en Colly: el modelo Collector\u003C\u002Fh2>\n\n\u003Cp>Colly se construye alrededor del tipo \u003Ccode>colly.Collector\u003C\u002Fcode>, que orquesta el ciclo de vida completo de una petición HTTP: preparación, envío, parseo de respuesta y manejo de errores. El Collector expone hooks mediante callbacks idiomáticos que se encadenan en orden:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Ccode>OnRequest(func(r *colly.Request))\u003C\u002Fcode> — se ejecuta antes de cada petición; ideal para inyectar headers, modificar la URL o loggear.\u003C\u002Fli>\n\u003Cli>\u003Ccode>OnHTML(selector string, func(e *colly.HTMLElement))\u003C\u002Fcode> — parsea el DOM con \u003Ca href=\"https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002FPuerkitoBio\u002Fgoquery\" rel=\"noopener noreferrer\">goquery\u003C\u002Fa>; permite extraer texto, atributos y recorrer elementos.\u003C\u002Fli>\n\u003Cli>\u003Ccode>OnError(func(r *colly.Response, err error))\u003C\u002Fcode> — captura errores de red, timeouts y respuestas con códigos no esperados.\u003C\u002Fli>\n\u003Cli>\u003Ccode>OnResponse(func(r *colly.Response))\u003C\u002Fcode> — se invoca con la respuesta cruda, antes del parseo HTML.\u003C\u002Fli>\n\u003Cli>\u003Ccode>OnScraped(func(r *colly.Response))\u003C\u002Fcode> — se ejecuta después de procesar todos los callbacks OnHTML.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>El Collector opera de forma asíncrona por defecto: cada llamada a \u003Ccode>c.Visit(url)\u003C\u002Fcode> encola una petición que se procesa concurrentemente según las reglas definidas por \u003Ccode>c.Limit()\u003C\u002Fcode>. Esto significa que la rotación de proxies debe ser segura para concurrencia —un detalle que veremos más adelante.\u003C\u002Fp>\n\n\u003Cp>El DOM traversal se delega a goquery, que expone una API similar a jQuery: \u003Ccode>e.Find(\"div.product\")\u003C\u002Fcode>, \u003Ccode>e.Attr(\"href\")\u003C\u002Fcode>, \u003Ccode>e.Text\u003C\u002Fcode>. Esto hace que la extracción sea declarativa y separe la lógica de parseo del transporte HTTP.\u003C\u002Fp>\n\n\u003Ch3>Ejemplo: Collector básico con callbacks\u003C\u002Fh3>\n\n\u003Cpre>\u003Ccode>package main\n\nimport (\n    &quot;fmt&quot;\n    &quot;log&quot;\n\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2&quot;\n)\n\nfunc main() {\n    c := colly.NewCollector(\n        colly.UserAgent(&quot;Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)&quot;),\n    )\n\n    c.OnRequest(func(r *colly.Request) {\n        fmt.Println(&quot;Visitando:&quot;, r.URL.String())\n    })\n\n    c.OnHTML(&quot;h1&quot;, func(e *colly.HTMLElement) {\n        fmt.Println(&quot;Titulo:&quot;, e.Text)\n    })\n\n    c.OnError(func(r *colly.Response, err error) {\n        log.Printf(&quot;Error en %s: %v&quot;, r.Request.URL, err)\n    })\n\n    c.Visit(&quot;https:\u002F\u002Fexample.com&quot;)\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Este patrón es la base. La rotación de proxies no cambia la estructura de tus callbacks —se inserta como una capa de transporte transparente mediante \u003Ccode>c.SetProxyFunc()\u003C\u002Fcode>.\u003C\u002Fp>\n\n\u003Ch2>La superficie idiomática de proxies en Colly\u003C\u002Fh2>\n\n\u003Cp>Colly ofrece dos mecanismos para rotar proxies, ambos idiomáticos y basados en el paquete \u003Ccode>proxy\u003C\u002Fcode>:\u003C\u002Fp>\n\n\u003Ch3>1. proxy.RoundRobinProxySwitcher\u003C\u002Fh3>\n\n\u003Cp>El switcher round-robin distribuye las peticiones secuencialmente entre una lista de URLs de proxy. Es la opción más simple cuando tienes un pool estático de endpoints:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import (\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2&quot;\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2\u002Fproxy&quot;\n)\n\nfunc main() {\n    c := colly.NewCollector()\n\n    proxyURLs := []string{\n        &quot;http:\u002F\u002Fuser-country-US:PASSWORD@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-DE:PASSWORD@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-GB:PASSWORD@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-FR:PASSWORD@gate.proxyhat.com:8080&quot;,\n    }\n\n    rp, err := proxy.RoundRobinProxySwitcher(proxyURLs...)\n    if err != nil {\n        log.Fatal(err)\n    }\n    c.SetProxyFunc(rp)\n\n    c.OnHTML(&quot;body&quot;, func(e *colly.HTMLElement) {\n        fmt.Println(e.Text)\n    })\n\n    c.Visit(&quot;https:\u002F\u002Fhttpbin.org\u002Fip&quot;)\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>El \u003Cstrong>colly proxy switcher\u003C\u002Fstrong> round-robin es thread-safe: usa un \u003Ccode>sync.Mutex\u003C\u002Fcode> interno para alternar el índice del proxy. Sin embargo, no soporta lógica condicional (por ejemplo, asignar un proxy específico según el dominio de destino).\u003C\u002Fp>\n\n\u003Ch3>2. Custom func(*http.Request) (*url.URL, error)\u003C\u002Fh3>\n\n\u003Cp>Para control total, Colly acepta cualquier función con la firma \u003Ccode>func(*http.Request) (*url.URL, error)\u003C\u002Fcode> vía \u003Ccode>c.SetProxyFunc()\u003C\u002Fcode>. Esto permite rotación dinámica basada en el dominio destino, estado de la sesión, geo-targeting o cualquier criterio:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import (\n    &quot;fmt&quot;\n    &quot;math\u002Frand&quot;\n    &quot;net\u002Fhttp&quot;\n    &quot;net\u002Furl&quot;\n    &quot;time&quot;\n\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2&quot;\n)\n\nfunc main() {\n    c := colly.NewCollector()\n\n    countries := []string{&quot;US&quot;, &quot;DE&quot;, &quot;GB&quot;, &quot;FR&quot;, &quot;ES&quot;, &quot;IT&quot;, &quot;NL&quot;}\n    cities := map[string]string{\n        &quot;US&quot;: &quot;new_york_city&quot;, &quot;DE&quot;: &quot;berlin&quot;, &quot;GB&quot;: &quot;london&quot;,\n        &quot;FR&quot;: &quot;paris&quot;, &quot;ES&quot;: &quot;madrid&quot;, &quot;IT&quot;: &quot;rome&quot;, &quot;NL&quot;: &quot;amsterdam&quot;,\n    }\n    regions := map[string]string{\n        &quot;US&quot;: &quot;new_york&quot;, &quot;DE&quot;: &quot;state_of_berlin&quot;, &quot;GB&quot;: &quot;england&quot;,\n        &quot;FR&quot;: &quot;ile_de_france&quot;, &quot;ES&quot;: &quot;madrid&quot;, &quot;IT&quot;: &quot;lazio&quot;, &quot;NL&quot;: &quot;north_holland&quot;,\n    }\n\n    rnd := rand.New(rand.NewSource(time.Now().UnixNano()))\n\n    c.SetProxyFunc(func(req *http.Request) (*url.URL, error) {\n        country := countries[rnd.Intn(len(countries))]\n        region := regions[country]\n        city := cities[country]\n        session := fmt.Sprintf(&quot;sess-%d&quot;, rnd.Intn(100000))\n\n        proxyStr := fmt.Sprintf(\n            &quot;http:\u002F\u002Fuser-country-%s-region-%s-city-%s-sid-%s:PASSWORD@gate.proxyhat.com:8080&quot;,\n            country, region, city, session,\n        )\n        return url.Parse(proxyStr)\n    })\n\n    c.OnHTML(&quot;body&quot;, func(e *colly.HTMLElement) {\n        fmt.Println(&quot;IP visible:&quot;, e.Text)\n    })\n\n    for i := 0; i &lt; 5; i++ {\n        c.Visit(&quot;https:\u002F\u002Fhttpbin.org\u002Fip&quot;)\n    }\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Este patrón es el recomendado para \u003Cstrong>golang colly proxy\u003C\u002Fstrong> en producción: cada petición obtiene una IP residencial diferente con geo-targeting a nivel de ciudad y una sesión única que evita correlación entre peticiones.\u003C\u002Fp>\n\n\u003Ch2>Por qué proxies residenciales para Colly web scraping\u003C\u002Fh2>\n\n\u003Cp>Los sitios modernos detectan y bloquean IPs de datacenter con alta precisión. Servicios como Cloudflare, Datadome y PerimeterX mantienen bases de datos de rangos ASN de hosting providers. Un proxy residencial, en cambio, usa IPs asignadas por ISPs legítimos a usuarios reales, lo que reduce drásticamente la probabilidad de bloqueo.\u003C\u002Fp>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Característica\u003C\u002Fth>\n\u003Cth>Residencial\u003C\u002Fth>\n\u003Cth>Datacenter\u003C\u002Fth>\n\u003Cth>Móvil\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Detección por anti-bot\u003C\u002Ftd>\n\u003Ctd>Baja\u003C\u002Ftd>\n\u003Ctd>Alta\u003C\u002Ftd>\n\u003Ctd>Muy baja\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Latencia típica\u003C\u002Ftd>\n\u003Ctd>200-800ms\u003C\u002Ftd>\n\u003Ctd>50-100ms\u003C\u002Ftd>\n\u003Ctd>500-2000ms\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Coste por GB\u003C\u002Ftd>\n\u003Ctd>Medio\u003C\u002Ftd>\n\u003Ctd>Bajo\u003C\u002Ftd>\n\u003Ctd>Alto\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Ideal para\u003C\u002Ftd>\n\u003Ctd>SERP, e-commerce, social\u003C\u002Ftd>\n\u003Ctd>APIs públicas, datos abiertos\u003C\u002Ftd>\n\u003Ctd>Apps móviles, login social\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cp>Para \u003Cstrong>colly web scraping\u003C\u002Fstrong> en sitios protegidos, los proxies residenciales son la opción por defecto. La rotación se controla desde el nombre de usuario en ProxyHat:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Ccode>user-country-DE:pass\u003C\u002Fcode> — IP aleatoria en Alemania.\u003C\u002Fli>\n\u003Cli>\u003Ccode>user-country-DE-region-state_of_berlin-city-berlin:pass\u003C\u002Fcode> — IP en Berlín específicamente.\u003C\u002Fli>\n\u003Cli>\u003Ccode>user-sid-abc123:pass\u003C\u002Fcode> — sesión sticky: la misma IP se mantiene entre peticiones con el mismo identificador de sesión.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>La combinación de rotación por país y sesiones sticky es clave: usa sesiones cuando necesites mantener estado (login, carrito de compra) y rotación pura cuando solo necesitas evadir rate limits. Consulta las \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">documentaciones de ProxyHat\u003C\u002Fa> para ver todos los parámetros disponibles.\u003C\u002Fp>\n\n\u003Ch2>Ejemplo completo: scraper con rotación residencial y Limit()\u003C\u002Fh2>\n\n\u003Cp>El siguiente ejemplo integra todos los componentes: un Collector con rotación de proxies residenciales por país, reglas de rate limiting, y manejo de errores con reintentos:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>package main\n\nimport (\n    &quot;crypto\u002Ftls&quot;\n    &quot;fmt&quot;\n    &quot;log&quot;\n    &quot;math\u002Frand&quot;\n    &quot;net\u002Fhttp&quot;\n    &quot;net\u002Furl&quot;\n    &quot;sync&quot;\n    &quot;time&quot;\n\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2&quot;\n    &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2\u002Fextensions&quot;\n)\n\nfunc main() {\n    c := colly.NewCollector(\n        colly.MaxDepth(2),\n        colly.AllowURLRevisit(false),\n    )\n\n    \u002F\u002F Transport TLS personalizado para evadir fingerprinting\n    c.WithTransport(&amp;http.Transport{\n        TLSClientConfig: &amp;tls.Config{\n            MinVersion: tls.VersionTLS12,\n        },\n        MaxIdleConns:        100,\n        MaxIdleConnsPerHost: 10,\n        IdleConnTimeout:     90 * time.Second,\n    })\n\n    \u002F\u002F Rate limiting: 20 conexiones concurrentes, 2s de delay\n    c.Limit(&amp;colly.LimitRule{\n        DomainGlob:  &quot;*&quot;,\n        Parallelism:  20,\n        Delay:        2 * time.Second,\n        RandomDelay:  1 * time.Second,\n    })\n\n    \u002F\u002F Rotacion de proxies residenciales con geo-targeting\n    countries := []string{&quot;US&quot;, &quot;DE&quot;, &quot;GB&quot;, &quot;FR&quot;, &quot;ES&quot;, &quot;IT&quot;, &quot;NL&quot;, &quot;CA&quot;, &quot;AU&quot;, &quot;JP&quot;}\n    var mu sync.Mutex\n    rnd := rand.New(rand.NewSource(time.Now().UnixNano()))\n\n    c.SetProxyFunc(func(req *http.Request) (*url.URL, error) {\n        mu.Lock()\n        country := countries[rnd.Intn(len(countries))]\n        session := fmt.Sprintf(&quot;sess-%d&quot;, rnd.Intn(1000000))\n        mu.Unlock()\n\n        proxyStr := fmt.Sprintf(\n            &quot;http:\u002F\u002Fuser-country-%s-sid-%s:PASSWORD@gate.proxyhat.com:8080&quot;,\n            country, session,\n        )\n        return url.Parse(proxyStr)\n    })\n\n    \u002F\u002F Headers realistas\n    extensions.RandomUserAgent(c)\n    c.OnRequest(func(r *colly.Request) {\n        r.Headers.Set(&quot;Accept-Language&quot;, &quot;en-US,en;q=0.9&quot;)\n        r.Headers.Set(&quot;Accept&quot;, &quot;text\u002Fhtml,application\u002Fxhtml+xml&quot;)\n    })\n\n    \u002F\u002F Reintentos con Clone\n    c.OnError(func(r *colly.Response, err error) {\n        if r.StatusCode &gt;= 500 || r.StatusCode == 429 {\n            log.Printf(&quot;Reintentando %s (status %d)&quot;, r.Request.URL, r.StatusCode)\n            r.Request.Retry()\n        }\n    })\n\n    c.OnHTML(&quot;a[href]&quot;, func(e *colly.HTMLElement) {\n        link := e.Attr(&quot;href&quot;)\n        fmt.Println(&quot;Encontrado:&quot;, link)\n        e.Request.Visit(link)\n    })\n\n    c.Visit(&quot;https:\u002F\u002Fexample.com&quot;)\n    c.Wait()\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Notar el uso de \u003Ccode>sync.Mutex\u003C\u002Fcode> para proteger el generador de números aleatorios —necesario porque Colly invoca \u003Ccode>SetProxyFunc\u003C\u002Fcode> desde múltiples goroutines. Omitir esto causa data races que son difíciles de debuggear.\u003C\u002Fp>\n\n\u003Ch2>Patrones de producción para scraping distribuido\u003C\u002Fh2>\n\n\u003Ch3>Reintentos con c.Clone()\u003C\u002Fh3>\n\n\u003Cp>Para reintentos más sofisticados, clona el Collector con \u003Ccode>c.Clone()\u003C\u002Fcode>. El clon hereda la configuración del padre pero puede tener su propio proxy, timeout y reglas. Esto permite estrategias como: primer intento con proxy residencial, reintento con proxy de otro país:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>c.OnError(func(r *colly.Response, err error) {\n    if r.StatusCode == 403 {\n        clone := c.Clone()\n        clone.SetProxyFunc(func(req *http.Request) (*url.URL, error) {\n            return url.Parse(&quot;http:\u002F\u002Fuser-country-US-sid-retry:PASSWORD@gate.proxyhat.com:8080&quot;)\n        })\n        clone.Visit(r.Request.URL.String())\n    }\n})\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>RandomDelay y Parallelism\u003C\u002Fh3>\n\n\u003Cp>El \u003Ccode>RandomDelay\u003C\u002Fcode> añade jitter al \u003Ccode>Delay\u003C\u002Fcode> base, lo que hace que tu tráfico sea menos predecible. Una configuración de \u003Ccode>Delay: 2s\u003C\u002Fcode> + \u003Ccode>RandomDelay: 1s\u003C\u002Fcode> produce esperas uniformemente distribuidas entre 2 y 3 segundos. Combinado con \u003Ccode>Parallelism: 20\u003C\u002Fcode>, obtienes 20 conexiones concurrentes con delays aleatorios —suficiente para la mayoría de sitios sin disparar rate limits.\u003C\u002Fp>\n\n\u003Ch3>Storage backends: Redis para scraping distribuido\u003C\u002Fh3>\n\n\u003Cp>Para fleets de scraping distribuido en múltiples contenedores o máquinas, Colly soporta backends de almacenamiento que comparten estado de visitación. El backend Redis evita que múltiples workers visiten la misma URL:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import &quot;github.com\u002Fgocolly\u002Fcolly\u002Fv2\u002Fstorage&quot;\n\ns := &amp;storage.RedisStorage{\n    Address: &quot;redis-cluster.internal:6379&quot;,\n    DB:      0,\n    Prefix:  &quot;colly_scraper_&quot;,\n}\nif err := s.Init(); err != nil {\n    log.Fatal(err)\n}\nc.SetStorage(s)\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Esto es esencial cuando escalas a 100+ workers: sin almacenamiento compartido, cada worker mantiene su propio set de URLs visitadas y duplica trabajo. Con Redis, el dedup es global y atómico.\u003C\u002Fp>\n\n\u003Ch3>SOCKS5 como alternativa\u003C\u002Fh3>\n\n\u003Cp>Cuando necesitas evadir inspección profunda de paquetes (DPI) o el tráfico HTTP CONNECT es bloqueado, SOCKS5 es una alternativa. Colly lo soporta nativamente cambiando el esquema y puerto:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>proxyStr := &quot;socks5:\u002F\u002Fuser-country-DE-sid-abc123:PASSWORD@gate.proxyhat.com:1080&quot;\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>SOCKS5 opera a nivel TCP sin interpretar HTTP, lo que lo hace más difícil de detectar en algunos firewalls corporativos.\u003C\u002Fp>\n\n\u003Ch2>Cuándo NO usar Colly y consideraciones éticas\u003C\u002Fh2>\n\n\u003Cp>Colly es excelente para sitios con HTML renderizado en servidor. Pero si el sitio es una SPA (Single Page Application) que renderiza todo con JavaScript —React, Vue, Angular— necesitas un navegador headless. Colly no ejecuta JavaScript. En ese caso, considera \u003Ca href=\"https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fchromedp\u002Fchromedp\" rel=\"noopener noreferrer\">chromedp\u003C\u002Fa> o Playwright para Go, y usa proxies a nivel del navegador.\u003C\u002Fp>\n\n\u003Cp>Antes de scrape cualquier sitio, verifica:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>\u003Cstrong>robots.txt\u003C\u002Fstrong>: respeta las directivas \u003Ccode>Disallow\u003C\u002Fcode>. El \u003Ca href=\"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc9309\" rel=\"noopener noreferrer\">RFC 9309\u003C\u002Fa> define el protocolo formal.\u003C\u002Fli>\n\u003Cli>Términos de servicio: algunos sitios prohíben explícitamente el scraping automatizado.\u003C\u002Fli>\n\u003Cli>Datos personales: el scraping de datos personales está sujeto al GDPR en la UE y al CCPA en California.\u003C\u002Fli>\n\u003Cli>Rate limits: no satures el servidor. Usa \u003Ccode>Limit()\u003C\u002Fcode> con delays razonables.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>El scraping de datos públicos es legal en muchas jurisdicciones, pero la línea entre \"público\" y \"protegido\" varía. Consulta con un abogado si tienes dudas sobre un caso específico.\u003C\u002Fp>\n\n\u003Ch2>Puntos clave (Key Takeaways)\u003C\u002Fh2>\n\n\u003Cblockquote>\n\u003Cp>Resumen de rotación de proxies en Colly:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Usa \u003Ccode>proxy.RoundRobinProxySwitcher\u003C\u002Fcode> para pools estáticos y \u003Ccode>SetProxyFunc\u003C\u002Fcode> con función personalizada para rotación dinámica.\u003C\u002Fli>\n\u003Cli>Los proxies residenciales reducen bloqueos en sitios protegidos; combina \u003Ccode>-country-XX\u003C\u002Fcode> y \u003Ccode>-sid-xxx\u003C\u002Fcode> en el username para control granular.\u003C\u002Fli>\n\u003Cli>Protege generadores de números aleatorios con \u003Ccode>sync.Mutex\u003C\u002Fcode> en el switcher personalizado —Colly invoca la función desde múltiples goroutines.\u003C\u002Fli>\n\u003Cli>Configura \u003Ccode>Limit()\u003C\u002Fcode> con \u003Ccode>Parallelism\u003C\u002Fcode> y \u003Ccode>RandomDelay\u003C\u002Fcode> para evitar rate limits; usa Redis storage para scraping distribuido.\u003C\u002Fli>\n\u003Cli>Colly no ejecuta JavaScript; para SPAs usa chromedp o Playwright con proxies a nivel de navegador.\u003C\u002Fli>\n\u003Cli>Respeta robots.txt, ToS y leyes de protección de datos antes de scrape.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fblockquote>\n\n\u003Cp>Para empezar con proxies residenciales en Colly, consulta nuestra \u003Ca href=\"\u002Fes\u002Fpricing\">página de precios\u003C\u002Fa>, explora los \u003Ca href=\"\u002Fes\u002Fuse-cases\u002Fweb-scraping\">casos de uso de web scraping\u003C\u002Fa> y \u003Ca href=\"\u002Fes\u002Fuse-cases\u002Fserp-tracking\">SERP tracking\u003C\u002Fa>, o revisa las \u003Ca href=\"\u002Fes\u002Flocations\">ubicaciones disponibles\u003C\u002Fa> en ProxyHat.\u003C\u002Fp>","Rotación de proxies en Colly: guía Go | ProxyHat","Aprende rotación de proxies en Colly con ejemplos en Go: RoundRobinProxySwitcher, proxies residenciales, sesiones sticky y patrones de producción.","\u002Fes\u002Fblog\u002Frotacion-proxies-colly-golang-1",null,"https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Frotacion-proxies-colly-golang-1-og.webp",[17,20,23,26],{"question":18,"answer":19},"¿Por qué importa la rotación de proxies en Colly para usuarios de proxies?","Sin rotación de proxies, todas las peticiones de tu scraper salen desde la misma IP, lo que permite a los sitios objetivo detectar y bloquear tu tráfico rápidamente mediante rate limiting o bans por IP. La rotación distribuye las peticiones entre múltiples IPs residenciales, reduciendo la probabilidad de bloqueo y permitiendo mantener throughput sostenido en sitios con protección anti-bot.",{"question":21,"answer":22},"¿Qué tipo de proxy funciona mejor para la rotación de proxies en Colly?","Los proxies residenciales funcionan mejor para la mayoría de casos de uso en Colly, especialmente en sitios protegidos con Cloudflare o Datadome. Las IPs residenciales provienen de ISPs legítimos, lo que reduce la detección. Los proxies datacenter son más rápidos y económicos pero se detectan fácilmente. Los proxies móviles ofrecen la menor detección pero tienen mayor latencia y coste.",{"question":24,"answer":25},"¿Cómo evitas bloqueos al implementar rotación de proxies en Colly?","Para evitar bloqueos: usa proxies residenciales con rotación por país y sesión, configura c.Limit() con Parallelism y RandomDelay para simular tráfico humano, añade headers realistas con extensions.RandomUserAgent, implementa reintentos con c.Clone() para códigos 429 y 503, y usa sync.Mutex para proteger el generador de proxies en entornos concurrentes. También respeta robots.txt y mantén delays razonables.",{"question":27,"answer":28},"¿Puedo usar SOCKS5 con Colly y ProxyHat?","Sí, Colly soporta SOCKS5 nativamente. Solo necesitas cambiar el esquema de la URL del proxy a socks5:\u002F\u002F y usar el puerto 1080 en lugar de 8080. Por ejemplo: socks5:\u002F\u002Fuser-country-DE-sid-abc123:PASSWORD@gate.proxyhat.com:1080. SOCKS5 opera a nivel TCP sin interpretar HTTP, lo que puede ser útil cuando el tráfico HTTP CONNECT es bloqueado por firewalls.",false,"2026-08-04T10:05:34+00:00","2026-10-03T23:53:00+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Frotacion-proxies-colly-golang-1-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Frotacion-proxies-colly-golang-1-card.webp",12,{"name":37,"slug":38,"bio":39,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[41],{"id":42,"slug":43,"name":44,"description":14,"meta_title":45,"meta_description":46,"parent_id":14},4,"guias-desarrolladores","Guías para Desarrolladores","Guías para Desarrolladores | Blog ProxyHat","Tutoriales de código y SDK para integrar proxies en tus aplicaciones.",[],{"es":13,"ja":49,"ru":50,"pt":51,"pl":52,"ko":53,"tr":54,"zh":55,"it":56,"de":57,"en":58,"fr":59,"x-default":58},"\u002Fja\u002Fblog\u002Fcolly-purokushi-roteshon-gaido","\u002Fru\u002Fblog\u002Frotaciya-proksi-v-colly-1","\u002Fpt\u002Fblog\u002Fproxies-rotativos-em-colly","\u002Fpl\u002Fblog\u002Frotacja-proxy-w-colly-1","\u002Fko\u002Fblog\u002Fcolly-rotating-proxy-guide","\u002Ftr\u002Fblog\u002Fcolly-doner-proxy-rehberi","\u002Fcn\u002Fblog\u002Fcolly-lunhuan-daili-shixian-zhinan","\u002Fit\u002Fblog\u002Fproxy-rotanti-in-colly-guida","\u002Fde\u002Fblog\u002Frotierende-proxies-in-colly","\u002Fblog\u002Frotating-proxies-in-colly-golang","\u002Ffr\u002Fblog\u002Frotation-proxies-colly-golang-1",{"es":13,"ja":49,"ru":50,"pt":51,"pl":52,"ko":53,"tr":54,"zh":55,"it":56,"de":57,"en":58,"fr":59},73,[63,79,95,111],{"id":64,"slug":65,"title":66,"excerpt":67,"featured_image_url":68,"featured_image_alt":69,"card_image_url":70,"og_image_url":71,"published_at":72,"updated_at":72,"content_updated_at":73,"reading_time_minutes":35,"is_featured":29,"indexable":29,"views":74,"author":75,"categories":76,"tags":78},176,"guia-got-scraping-nodejs-proxy-residencial","Guía de got-scraping en Node.js con proxies residenciales","Una guía práctica para desarrolladores sobre cómo usar got-scraping en Node.js: generador de cabeceras, HTTP\u002F2, proxies residenciales y patrones de producción con reintentos, concurrencia y Crawlee.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fguia-got-scraping-nodejs-proxy-residencial-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fguia-got-scraping-nodejs-proxy-residencial-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fguia-got-scraping-nodejs-proxy-residencial-og.webp","2026-08-04T16:05:06+00:00","2026-10-03T08:29:58+00:00",123,{"name":37,"slug":38,"bio":39,"avatar_url":14,"website_url":14,"social_links":14},[77],{"id":42,"slug":43,"name":44,"description":14,"meta_title":45,"meta_description":46,"parent_id":14},[],{"id":80,"slug":81,"title":82,"excerpt":83,"featured_image_url":84,"featured_image_alt":85,"card_image_url":86,"og_image_url":87,"published_at":88,"updated_at":88,"content_updated_at":89,"reading_time_minutes":35,"is_featured":29,"indexable":4,"views":90,"author":91,"categories":92,"tags":94},195,"scrapear-api-mercado-bybit-v5-proxies","Cómo extraer datos de mercado cripto con proxies rotativos: límites, geobloqueos y paginación (ejemplo: API V5 de Bybit)","Guía de desarrollo para extraer datos de mercado de Bybit V5 usando proxies residenciales rotativos. Cubre endpoints, rate limits, geo-bloqueos, sesiones sticky y ejemplos en Python y Node.js con ProxyHat.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-mercado-bybit-v5-proxies-master.webp","How to Scrape the Bybit V5 Market API with Rotating Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-mercado-bybit-v5-proxies-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-mercado-bybit-v5-proxies-og.webp","2026-08-03T16:09:16+00:00","2026-10-04T01:29:51+00:00",88,{"name":37,"slug":38,"bio":39,"avatar_url":14,"website_url":14,"social_links":14},[93],{"id":42,"slug":43,"name":44,"description":14,"meta_title":45,"meta_description":46,"parent_id":14},[],{"id":96,"slug":97,"title":98,"excerpt":99,"featured_image_url":100,"featured_image_alt":101,"card_image_url":102,"og_image_url":103,"published_at":104,"updated_at":104,"content_updated_at":105,"reading_time_minutes":35,"is_featured":29,"indexable":29,"views":106,"author":107,"categories":108,"tags":110},194,"scrapear-api-binance-proxies","Cómo scrapear la API REST de Binance con proxies: guía para desarrolladores","Guía técnica con código ejecutable para extraer datos públicos de mercado de la API REST de Binance a escala usando proxies residenciales rotativos. Cubre endpoints, rate limits, weight headers y estrategias de rotación de IP.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-binance-proxies-master.webp","How to Scrape the Binance REST API with Proxies: A Developer Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-binance-proxies-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fscrapear-api-binance-proxies-og.webp","2026-08-03T10:04:04+00:00","2026-10-03T08:21:32+00:00",82,{"name":37,"slug":38,"bio":39,"avatar_url":14,"website_url":14,"social_links":14},[109],{"id":42,"slug":43,"name":44,"description":14,"meta_title":45,"meta_description":46,"parent_id":14},[],{"id":112,"slug":113,"title":114,"excerpt":115,"featured_image_url":116,"featured_image_alt":117,"card_image_url":118,"og_image_url":119,"published_at":120,"updated_at":120,"content_updated_at":31,"reading_time_minutes":35,"is_featured":29,"indexable":29,"views":121,"author":122,"categories":123,"tags":125},172,"usar-proxies-en-swift-urlsession-1","Usar proxies en Swift con URLSession: guía práctica para iOS y macOS","Guía completa para configurar proxies residenciales en Swift usando URLSession, con ejemplos de código async\u002Fawait, autenticación, SOCKS5 y mejores prácticas de producción.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fusar-proxies-en-swift-urlsession-1-master.webp","Using Proxies in Swift: A Code-First Guide to URLSession, SOCKS5 & Residential IPs","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fusar-proxies-en-swift-urlsession-1-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fes\u002Fusar-proxies-en-swift-urlsession-1-og.webp","2026-07-26T16:03:44+00:00",235,{"name":37,"slug":38,"bio":39,"avatar_url":14,"website_url":14,"social_links":14},[124],{"id":42,"slug":43,"name":44,"description":14,"meta_title":45,"meta_description":46,"parent_id":14},[],[]]