[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-it-scraping-serp-geo-targetato-best-practices":3},{"success":4,"payload":5,"related":60,"errors":127},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":15,"og_image_url":16,"faq_json":17,"key_takeaways":14,"allow_index":27,"noindex_google_only":27,"allow_follow":4,"published_at":28,"updated_at":28,"content_updated_at":29,"featured_image_url":30,"featured_image_alt":31,"card_image_url":32,"reading_time_minutes":33,"author":34,"categories":38,"tags":45,"alternates":46,"locale_paths":48,"views":59},198,"scraping-serp-geo-targetato-best-practices","Best Practices per Scraping SERP Geo-Targetato: Guida per Sviluppatori","Scopri come implementare scraping SERP geo-targetato con precisione a livello città usando parametri uule, gl, hl e proxy residenziali. Esempi Python e curl pronti all'uso.","\u003Ch2>Best Practices per Scraping SERP Geo-Targetato: Perché la Posizione Cambia Tutto\u003C\u002Fh2>\n\u003Cp>Se hai mai cercato la stessa keyword da due città diverse e ottenuto risultati completamente differenti, hai già sperimentato il problema centrale del scraping SERP geo-targetato. Google personalizza i risultati in base alla posizione geografica dell'utente: un'azienda di pizzerie a Milano appare nei risultati locali per \"pizza\" cercato da Roma solo se ha una sede lì, e il \u003Cem>local pack\u003C\u002Fem> (le tre mappe in cima) cambia radicalmente tra quartieri della stessa città.\u003C\u002Fp>\n\u003Cp>Per i team SEO e i rank tracker, questo significa che raccogliere SERP senza specificare una località precisa produce dati inutilizzabili. Il targeting a livello paese non basta: \"caffè a Roma\" e \"caffè a Napoli\" generano SERP diverse, e anche dentro Roma i risultati del centro storico differiscono da quelli della periferia. Le best practices per scraping SERP geo-targetato richiedono precisione a livello città, parametri di localizzazione coerenti e IP residenziali allineati al mercato target.\u003C\u002Fp>\n\u003Ch2>Perché la Stessa Query Restituisce Risultati Diversi per Località\u003C\u002Fh2>\n\u003Cp>Google utilizza almeno tre segnali per localizzare i risultati di ricerca:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Geolocalizzazione IP\u003C\u002Fstrong>: Google deduce la posizione approssimativa dall'indirizzo IP del richiedente. Un IP statunitense produce risultati US, un IP italiano risultati IT.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Parametri URL\u003C\u002Fstrong>: \u003Ccode>gl\u003C\u002Fcode>, \u003Ccode>hl\u003C\u002Fcode>, \u003Ccode>google_domain\u003C\u002Fcode>, \u003Ccode>uule\u003C\u002Fcode> e \u003Ccode>pws\u003C\u002Fcode> comunicano esplicitamente la regione, la lingua e la città desiderate.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Account e cookie\u003C\u002Fstrong>: lo storico di ricerca e le impostazioni dell'account influenzano la personalizzazione — ma per scraping impersonale si usa \u003Ccode>pws=0\u003C\u002Fcode> per disattivarla.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Il problema è che \u003Cstrong>Google cross-controlla questi segnali\u003C\u002Fstrong>. Se invii \u003Ccode>gl=US\u003C\u002Fcode> ma il tuo IP è in Francia, Google può ignorare il parametro o mostrare risultati ibridi. Per risultati affidabili e riproducibili, IP e parametri URL devono concordare. Per approfondire il funzionamento dei parametri di localizzazione, consulta la documentazione ufficiale di Google.\u003C\u002Fp>\n\u003Ch3>Perché il Targeting a Livello Paese Non È Sufficiente\u003C\u002Fh3>\n\u003Cp>Il \u003Cem>local pack\u003C\u002Fem> — quel blocco di tre risultati con mappa che appare per query con intento locale — è sensibile alla posizione fino al livello di quartiere. Un'azienda di idraulici a Brooklyn non appare nel local pack per \"idraulico\" cercato da Manhattan, anche se entrambe sono a New York City. Per il rank tracking locale serve precisione a livello città o distretto, non solo paese.\u003C\u002Fp>\n\u003Cp>Secondo le impostazioni di regione di Google, la localizzazione influisce su ordinamento, local pack, suggerimenti e persino le featured snippets. Ignorare questo significa raccogliere dati SERP che non riflettono ciò che vedono gli utenti reali nel mercato target.\u003C\u002Fp>\n\u003Ch2>Parametri di Localizzazione Core: gl, hl, google_domain, lr, uule, pws\u003C\u002Fh2>\n\u003Cp>Ecco i parametri essenziali per il scraping SERP geo-targetato, con la loro funzione e valori comuni:\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Parametro\u003C\u002Fth>\u003Cth>Funzione\u003C\u002Fth>\u003Cth>Esempio\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Ccode>gl\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Codice paese (ISO 3166-1 alpha-2)\u003C\u002Ftd>\u003Ctd>\u003Ccode>gl=us\u003C\u002Fcode>, \u003Ccode>gl=it\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>hl\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Lingua interfaccia (ISO 639-1)\u003C\u002Ftd>\u003Ctd>\u003Ccode>hl=it\u003C\u002Fcode>, \u003Ccode>hl=en\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>google_domain\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Dominio Google regionale\u003C\u002Ftd>\u003Ctd>\u003Ccode>google_domain=google.it\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>lr\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Filtro lingua dei risultati\u003C\u002Ftd>\u003Ctd>\u003Ccode>lang_it\u003C\u002Fcode>, \u003Ccode>lang_en\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>uule\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Località precisa (città\u002Fdistretto)\u003C\u002Ftd>\u003Ctd>\u003Ccode>uule=w+CAIQICI...\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>pws\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Personalizzazione (0 = off)\u003C\u002Ftd>\u003Ctd>\u003Ccode>pws=0\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3>Costruire il Parametro uule\u003C\u002Fh3>\n\u003Cp>Il parametro \u003Ccode>uule\u003C\u002Fcode> è il più critico e meno documentato. Permette di specificare una località precisa a livello città. Il formato è:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>uule = &quot;w+CAIQICI&quot; + base64(canonical_place_name)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Dove \u003Ccode>canonical_place_name\u003C\u002Fcode> è una stringa nel formato \"Città,Regione,Paese\" (in inglese canonico). Ad esempio:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\"Rome,Lazio,Italy\" per Roma\u003C\u002Fli>\n\u003Cli>\"Milan,Lombardy,Italy\" per Milano\u003C\u002Fli>\n\u003Cli>\"Brooklyn,New York,United States\" per Brooklyn, NYC\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>La regola d'oro: aggiungi sempre \u003Ccode>pws=0\u003C\u002Fcode> per ottenere un baseline non personalizzato, riproducibile tra esecuzioni. Senza \u003Ccode>pws=0\u003C\u002Fcode>, Google può iniettare risultati personalizzati basati su segnali dell'IP, rendendo i dati non riproducibili.\u003C\u002Fp>\n\u003Ch2>Allineamento IP-Parametri: Perché Serve un Proxy Residenziale\u003C\u002Fh2>\n\u003Cp>Se i tuoi parametri URL dicono \u003Ccode>gl=US&amp;uule=...New York\u003C\u002Fcode> ma il tuo IP è in Germania, Google rileva l'incongruenza. I datacenter IP sono inoltre facilmente identificabili e spesso bloccati. La soluzione è routare le richieste attraverso proxy residenziali localizzati nella stessa area geografica dei parametri.\u003C\u002Fp>\n\u003Cp>Con ProxyHat, puoi specificare paese e città direttamente nel username del proxy:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>http:\u002F\u002Fuser-country-US-region-new_york-city-new_york_city:password@gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Questo garantisce che ogni richiesta arrivi da un IP residenziale statunitense localizzato a New York, allineato con \u003Ccode>gl=us\u003C\u002Fcode> e \u003Ccode>uule=...New York\u003C\u002Fcode>. Consulta tutte le \u003Ca href=\"\u002Fit\u002Flocations\">locazioni disponibili\u003C\u002Fa> per verificare la copertura e il \u003Ca href=\"\u002Fit\u002Fpricing\">piano tariffario\u003C\u002Fa> più adatto al tuo volume.\u003C\u002Fp>\n\u003Ch2>Implementazione Pratica: Esempi di Codice\u003C\u002Fh2>\n\u003Ch3>1. Costruire uule e Inviare una Richiesta SERP con curl\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>#!\u002Fbin\u002Fbash\n# Costruisce uule per Rome, Italy e invia una richiesta SERP tramite proxy residenziale ProxyHat\n\nUULE=$(echo -n &quot;Rome,Lazio,Italy&quot; | base64)\nQUERY=&quot;pizzeria&quot;\nURL=&quot;https:\u002F\u002Fwww.google.com\u002Fsearch?q=${QUERY}&amp;gl=it&amp;hl=it&amp;google_domain=google.it&amp;pws=0&amp;uule=w+CAIQICI${UULE}&amp;num=20&quot;\n\ncurl -sS \\\n  --proxy &quot;http:\u002F\u002Fuser-country-IT-region-lazio-city-rome:password@gate.proxyhat.com:8080&quot; \\\n  -H &quot;User-Agent: Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36 (KHTML, like Gecko) Chrome\u002F124.0.0.0 Safari\u002F537.36&quot; \\\n  -H &quot;Accept-Language: it-IT,it;q=0.9,en;q=0.8&quot; \\\n  &quot;$URL&quot; -o serp_rome.html\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>2. Python requests con Proxy Residenziale e uule (Raw Proxy)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>import base64\nimport requests\nfrom urllib.parse import urlencode\n\ndef build_uule(canonical_name: str) -&gt; str:\n    &quot;&quot;&quot;Costruisce il parametro uule di Google per targeting a livello città.&quot;&quot;&quot;\n    prefix = &quot;w+CAIQICI&quot;\n    encoded = base64.b64encode(canonical_name.encode(&quot;utf-8&quot;)).decode(&quot;ascii&quot;)\n    return prefix + encoded\n\ndef scrape_serp_raw(\n    query: str,\n    country: str,\n    lang: str,\n    google_domain: str,\n    canonical_place: str,\n    proxy_country: str,\n    proxy_region: str,\n    proxy_city: str,\n    proxy_pass: str,\n    num: int = 20,\n) -&gt; str:\n    &quot;&quot;&quot;Scraping SERP geo-targetato con proxy residenziale raw.&quot;&quot;&quot;\n    uule = build_uule(canonical_place)\n    params = {\n        &quot;q&quot;: query,\n        &quot;gl&quot;: country,\n        &quot;hl&quot;: lang,\n        &quot;google_domain&quot;: google_domain,\n        &quot;uule&quot;: uule,\n        &quot;pws&quot;: &quot;0&quot;,\n        &quot;num&quot;: str(num),\n    }\n    url = f&quot;https:\u002F\u002Fwww.google.{google_domain.split(&apos;.&apos;)[-1]}\u002Fsearch?&quot; + urlencode(params)\n\n    proxy_url = f&quot;http:\u002F\u002Fuser-country-{proxy_country}-region-{proxy_region}-city-{proxy_city}:{proxy_pass}@gate.proxyhat.com:8080&quot;\n    proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n\n    headers = {\n        &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36 (KHTML, like Gecko) Chrome\u002F124.0.0.0 Safari\u002F537.36&quot;,\n        &quot;Accept-Language&quot;: f&quot;{lang}-{country.upper()},{lang};q=0.9,en;q=0.8&quot;,\n        &quot;Accept&quot;: &quot;text\u002Fhtml,application\u002Fxhtml+xml,application\u002Fxml;q=0.9,*\u002F*;q=0.8&quot;,\n    }\n\n    resp = requests.get(url, proxies=proxies, headers=headers, timeout=30)\n    resp.raise_for_status()\n    return resp.text\n\n# Esempio: SERP per &quot;pizzeria&quot; a Roma\nhtml = scrape_serp_raw(\n    query=&quot;pizzeria&quot;,\n    country=&quot;it&quot;,\n    lang=&quot;it&quot;,\n    google_domain=&quot;google.it&quot;,\n    canonical_place=&quot;Rome,Lazio,Italy&quot;,\n    proxy_country=&quot;IT&quot;,\n    proxy_region=&quot;lazio&quot;,\n    proxy_city=&quot;rome&quot;,\n    proxy_pass=&quot;tua_password&quot;,\n)\nprint(f&quot;Ricevuti {len(html)} byte di HTML&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>3. ProxyHat SDK Client (Wrapper) per Gestione Multi-Locale\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>import base64\nimport logging\nfrom dataclasses import dataclass, field\nfrom typing import Optional\nimport requests\n\nlogger = logging.getLogger(&quot;proxyhat_serp&quot;)\n\n@dataclass\nclass LocaleConfig:\n    &quot;&quot;&quot;Configurazione locale per scraping SERP geo-targetato.&quot;&quot;&quot;\n    country: str          # es. &quot;US&quot;\n    region: str           # es. &quot;new_york&quot;\n    city: str             # es. &quot;new_york_city&quot;\n    gl: str               # es. &quot;us&quot;\n    hl: str               # es. &quot;en&quot;\n    google_domain: str    # es. &quot;google.com&quot;\n    canonical_place: str  # es. &quot;New York,New York,United States&quot;\n    lr: Optional[str] = None\n\n@dataclass\nclass ProxyHatClient:\n    &quot;&quot;&quot;Client ProxyHat per scraping SERP geo-targetato con rotazione residenziale.&quot;&quot;&quot;\n    username: str\n    password: str\n    gateway: str = &quot;gate.proxyhat.com&quot;\n    http_port: int = 8080\n    socks5_port: int = 1080\n    session: requests.Session = field(default_factory=requests.Session)\n\n    def _proxy_url(self, locale: LocaleConfig, session_id: Optional[str] = None) -&gt; str:\n        &quot;&quot;&quot;Costruisce l&apos;URL del proxy con geo-targeting.&quot;&quot;&quot;\n        user = f&quot;user-country-{locale.country}-region-{locale.region}-city-{locale.city}&quot;\n        if session_id:\n            user += f&quot;-sid-{session_id}&quot;\n        return f&quot;http:\u002F\u002F{user}:{self.password}@{self.gateway}:{self.http_port}&quot;\n\n    def build_uule(self, canonical_place: str) -&gt; str:\n        prefix = &quot;w+CAIQICI&quot;\n        return prefix + base64.b64encode(\n            canonical_place.encode(&quot;utf-8&quot;)\n        ).decode(&quot;ascii&quot;)\n\n    def scrape(self, query: str, locale: LocaleConfig,\n               num: int = 20, session_id: Optional[str] = None) -&gt; str:\n        &quot;&quot;&quot;Esegue scraping SERP geo-targetato con IP residenziale allineato.&quot;&quot;&quot;\n        uule = self.build_uule(locale.canonical_place)\n        params = {\n            &quot;q&quot;: query, &quot;gl&quot;: locale.gl, &quot;hl&quot;: locale.hl,\n            &quot;google_domain&quot;: locale.google_domain,\n            &quot;uule&quot;: uule, &quot;pws&quot;: &quot;0&quot;, &quot;num&quot;: str(num),\n        }\n        if locale.lr:\n            params[&quot;lr&quot;] = locale.lr\n\n        url = f&quot;https:\u002F\u002Fwww.{locale.google_domain}\u002Fsearch?&quot; + \\\n              &quot;&amp;&quot;.join(f&quot;{k}={v}&quot; for k, v in params.items())\n\n        proxy_url = self._proxy_url(locale, session_id)\n        proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n        headers = {\n            &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) &quot;\n                          &quot;AppleWebKit\u002F537.36 (KHTML, like Gecko) &quot;\n                          &quot;Chrome\u002F124.0.0.0 Safari\u002F537.36&quot;,\n            &quot;Accept-Language&quot;: f&quot;{locale.hl}-{locale.country},{locale.hl};q=0.9&quot;,\n        }\n\n        logger.info(f&quot;Scraping &apos;{query}&apos; per {locale.city} via {proxy_url}&quot;)\n        resp = self.session.get(url, proxies=proxies, headers=headers, timeout=30)\n        resp.raise_for_status()\n        return resp.text\n\n# Utilizzo\nclient = ProxyHatClient(username=&quot;user&quot;, password=&quot;pass&quot;)\n\nus_nyc = LocaleConfig(\n    country=&quot;US&quot;, region=&quot;new_york&quot;, city=&quot;new_york_city&quot;, gl=&quot;us&quot;, hl=&quot;en&quot;,\n    google_domain=&quot;google.com&quot;,\n    canonical_place=&quot;New York,New York,United States&quot;,\n    lr=&quot;lang_en&quot;,\n)\n\nhtml = client.scrape(&quot;best pizza near me&quot;, us_nyc, num=20)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>4. curl_cffi con Impersonazione Chrome e Proxy\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>import base64\nfrom curl_cffi import requests as cffi_requests\n\ndef build_uule(canonical_name: str) -&gt; str:\n    prefix = &quot;w+CAIQICI&quot;\n    return prefix + base64.b64encode(\n        canonical_name.encode(&quot;utf-8&quot;)\n    ).decode(&quot;ascii&quot;)\n\ndef scrape_serp_curl_cffi(query: str, canonical_place: str,\n                          gl: str, hl: str, domain: str,\n                          proxy_country: str, proxy_region: str, proxy_city: str,\n                          password: str) -&gt; str:\n    &quot;&quot;&quot;Scraping SERP con curl_cffi e impersonazione Chrome 120.&quot;&quot;&quot;\n    uule = build_uule(canonical_place)\n    params = {\n        &quot;q&quot;: query, &quot;gl&quot;: gl, &quot;hl&quot;: hl,\n        &quot;google_domain&quot;: domain, &quot;uule&quot;: uule,\n        &quot;pws&quot;: &quot;0&quot;, &quot;num&quot;: &quot;20&quot;,\n    }\n    url = f&quot;https:\u002F\u002Fwww.{domain}\u002Fsearch?&quot; + \\\n          &quot;&amp;&quot;.join(f&quot;{k}={v}&quot; for k, v in params.items())\n\n    proxy = (f&quot;http:\u002F\u002Fuser-country-{proxy_country}-region-{proxy_region}-city-{proxy_city}:&quot;\n             f&quot;{password}@gate.proxyhat.com:8080&quot;)\n\n    # impersonate=chrome120 replica TLS fingerprint e JA3 di Chrome 120\n    resp = cffi_requests.get(\n        url,\n        impersonate=&quot;chrome120&quot;,\n        proxies={&quot;http&quot;: proxy, &quot;https&quot;: proxy},\n        timeout=30,\n    )\n    resp.raise_for_status()\n    return resp.text\n\n# US geo-targeted SERP scraping best practices: New York\nhtml_nyc = scrape_serp_curl_cffi(\n    &quot;plumber&quot;, &quot;New York,New York,United States&quot;,\n    &quot;us&quot;, &quot;en&quot;, &quot;google.com&quot;, &quot;US&quot;, &quot;new_york&quot;, &quot;new_york_city&quot;, &quot;pass&quot;\n)\nprint(f&quot;NYC SERP: {len(html_nyc)} byte&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>5. Parsing Risultati Organici e Local Pack con selectolax\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>from selectolax.parser import HTMLParser\nfrom dataclasses import dataclass\nfrom typing import List\n\n@dataclass\nclass OrganicResult:\n    position: int\n    title: str\n    url: str\n    snippet: str\n\n@dataclass\nclass LocalPackResult:\n    name: str\n    rating: str\n    address: str\n\ndef parse_organic(html: str) -&gt; List[OrganicResult]:\n    &quot;&quot;&quot;Estrae i risultati organici dalla SERP.&quot;&quot;&quot;\n    tree = HTMLParser(html)\n    results = []\n    for i, div in enumerate(tree.css(&quot;div.g&quot;), start=1):\n        title_el = div.css_first(&quot;h3&quot;)\n        link_el = div.css_first(&quot;a[href]&quot;)\n        snippet_el = div.css_first(&quot;div.VwiC3b&quot;) or div.css_first(&quot;span.aCOpRe&quot;)\n        if title_el and link_el:\n            results.append(OrganicResult(\n                position=i,\n                title=title_el.text(strip=True),\n                url=link_el.attributes.get(&quot;href&quot;, &quot;&quot;),\n                snippet=snippet_el.text(strip=True) if snippet_el else &quot;&quot;,\n            ))\n    return results\n\ndef parse_local_pack(html: str) -&gt; List[LocalPackResult]:\n    &quot;&quot;&quot;Estrae il local pack (risultati con mappa).&quot;&quot;&quot;\n    tree = HTMLParser(html)\n    local_results = []\n    for item in tree.css(&quot;div[data-cid]&quot;):\n        name_el = item.css_first(&quot;div.fontHandle&quot;) or item.css_first(&quot;.dbg0pd&quot;)\n        if name_el:\n            name = name_el.text(strip=True)\n            rating = &quot;&quot;\n            address = &quot;&quot;\n            details = item.css_first(&quot;div.rllt__details&quot;)\n            if details:\n                spans = details.css(&quot;span&quot;)\n                if spans:\n                    rating = spans[0].text(strip=True) if spans else &quot;&quot;\n                    address = spans[-1].text(strip=True) if len(spans) &gt; 1 else &quot;&quot;\n            local_results.append(LocalPackResult(\n                name=name, rating=rating, address=address,\n            ))\n    return local_results\n\n# Utilizzo\norganic = parse_organic(html_nyc)\nlocal = parse_local_pack(html_nyc)\n\nprint(f&quot;Risultati organici: {len(organic)}&quot;)\nfor r in organic[:5]:\n    print(f&quot;  #{r.position}: {r.title} -- {r.url}&quot;)\n\nprint(f&quot;\\nLocal pack: {len(local)}&quot;)\nfor lp in local:\n    print(f&quot;  {lp.name} -- {lp.rating} -- {lp.address}&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>6. Sticky Session per SERP Multi-Pagina\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>import uuid\nimport time\nimport logging\nfrom typing import List, Dict\n\nlogger = logging.getLogger(&quot;serp_multipage&quot;)\n\ndef scrape_multi_page_serp(\n    client: ProxyHatClient,\n    query: str,\n    locale: LocaleConfig,\n    max_pages: int = 3,\n) -&gt; List[Dict]:\n    &quot;&quot;&quot;Scraping SERP multi-pagina con sticky session per coerenza IP.&quot;&quot;&quot;\n    session_id = uuid.uuid4().hex[:12]  # ID sessione stabile\n    all_results = []\n\n    for page in range(max_pages):\n        start_param = page * 10\n        uule = client.build_uule(locale.canonical_place)\n\n        params = {\n            &quot;q&quot;: query, &quot;gl&quot;: locale.gl, &quot;hl&quot;: locale.hl,\n            &quot;google_domain&quot;: locale.google_domain,\n            &quot;uule&quot;: uule, &quot;pws&quot;: &quot;0&quot;,\n            &quot;start&quot;: str(start_param),\n        }\n        url = f&quot;https:\u002F\u002Fwww.{locale.google_domain}\u002Fsearch?&quot; + \\\n              &quot;&amp;&quot;.join(f&quot;{k}={v}&quot; for k, v in params.items())\n\n        proxy_url = client._proxy_url(locale, session_id=session_id)\n        proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n        headers = {\n            &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) &quot;\n                          &quot;AppleWebKit\u002F537.36 Chrome\u002F124.0.0.0 Safari\u002F537.36&quot;,\n            &quot;Accept-Language&quot;: f&quot;{locale.hl}-{locale.country}&quot;,\n        }\n\n        logger.info(f&quot;Pagina {page+1}\u002F{max_pages} -- session={session_id}&quot;)\n        resp = client.session.get(url, proxies=proxies, headers=headers, timeout=30)\n        resp.raise_for_status()\n\n        organic = parse_organic(resp.text)\n        if not organic:\n            logger.warning(f&quot;Nessun risultato a pagina {page+1}, interruzione&quot;)\n            break\n\n        for r in organic:\n            all_results.append({\n                &quot;page&quot;: page + 1,\n                &quot;position&quot;: r.position + start_param,\n                &quot;title&quot;: r.title,\n                &quot;url&quot;: r.url,\n                &quot;snippet&quot;: r.snippet,\n            })\n\n        time.sleep(2)  # Rate limiting rispettoso\n\n    return all_results\n\n# Esempio: 3 pagine di SERP per &quot;dentist&quot; a Chicago\nchicago = LocaleConfig(\n    country=&quot;US&quot;, city=&quot;chicago&quot;, gl=&quot;us&quot;, hl=&quot;en&quot;,\n    google_domain=&quot;google.com&quot;,\n    canonical_place=&quot;Chicago,Illinois,United States&quot;,\n)\n\nresults = scrape_multi_page_serp(client, &quot;dentist&quot;, chicago, max_pages=3)\nprint(f&quot;Totali: {len(results)} risultati su {results[-1][&apos;page&apos;]} pagine&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>7. Retry, Backoff e Per-Country Proxy Pools\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>import time\nimport logging\nfrom functools import wraps\nfrom requests.exceptions import RequestException, HTTPError\n\nlogger = logging.getLogger(&quot;serp_retry&quot;)\n\ndef retry_with_backoff(max_retries: int = 3, base_delay: float = 2.0,\n                        backoff_factor: float = 2.0):\n    &quot;&quot;&quot;Decorator per retry con backoff esponenziale su 429\u002F503.&quot;&quot;&quot;\n    def decorator(func):\n        @wraps(func)\n        def wrapper(*args, **kwargs):\n            delay = base_delay\n            for attempt in range(1, max_retries + 1):\n                try:\n                    return func(*args, **kwargs)\n                except HTTPError as e:\n                    status = e.response.status_code if e.response else 0\n                    if status in (429, 503):\n                        wait = delay + (attempt * 1.5)\n                        logger.warning(\n                            f&quot;Tentativo {attempt}\u002F{max_retries}: &quot;\n                            f&quot;HTTP {status}, attesa {wait:.1f}s&quot;\n                        )\n                        time.sleep(wait)\n                        delay *= backoff_factor\n                    else:\n                        raise\n                except RequestException as e:\n                    logger.error(f&quot;Errore di rete: {e}&quot;)\n                    if attempt == max_retries:\n                        raise\n                    time.sleep(delay)\n                    delay *= backoff_factor\n            raise RuntimeError(f&quot;Fallito dopo {max_retries} tentativi&quot;)\n        return wrapper\n    return decorator\n\nclass CountryProxyPool:\n    &quot;&quot;&quot;Gestisce pool di proxy residenziali per paese con rotazione.&quot;&quot;&quot;\n\n    def __init__(self, username: str, password: str):\n        self.username = username\n        self.password = password\n        self.gateway = &quot;gate.proxyhat.com&quot;\n        self.port = 8080\n        # Mapping paese -&gt; lista (regione, citta) per rotazione\n        self.country_cities = {\n            &quot;US&quot;: [(&quot;new_york&quot;, &quot;new_york_city&quot;), (&quot;california&quot;, &quot;los_angeles&quot;), (&quot;illinois&quot;, &quot;chicago&quot;), (&quot;florida&quot;, &quot;miami&quot;), (&quot;washington&quot;, &quot;seattle&quot;)],\n            &quot;IT&quot;: [(&quot;lazio&quot;, &quot;rome&quot;), (&quot;lombardy&quot;, &quot;milan&quot;), (&quot;campania&quot;, &quot;naples&quot;), (&quot;piedmont&quot;, &quot;turin&quot;), (&quot;tuscany&quot;, &quot;florence&quot;)],\n            &quot;DE&quot;: [(&quot;state_of_berlin&quot;, &quot;berlin&quot;), (&quot;bayern&quot;, &quot;munich&quot;), (&quot;hessen&quot;, &quot;frankfurt_am_main&quot;), (&quot;hamburg&quot;, &quot;hamburg&quot;)],\n            &quot;GB&quot;: [(&quot;england&quot;, &quot;london&quot;), (&quot;england&quot;, &quot;manchester&quot;), (&quot;england&quot;, &quot;birmingham&quot;), (&quot;england&quot;, &quot;liverpool&quot;)],\n        }\n        self._rotation_idx = {}\n\n    def get_proxy(self, country: str, region: str = None, city: str = None,\n                  session_id: str = None) -&gt; str:\n        &quot;&quot;&quot;Restituisce URL proxy per paese\u002Fcitta con rotazione automatica.&quot;&quot;&quot;\n        if city is None:\n            cities = self.country_cities.get(country, [(None, None)])\n            idx = self._rotation_idx.get(country, 0)\n            region, city = cities[idx % len(cities)]\n            self._rotation_idx[country] = idx + 1\n\n        user = f&quot;user-country-{country}&quot;\n        if region and city:\n            user += f&quot;-region-{region}-city-{city}&quot;\n        elif region:\n            user += f&quot;-region-{region}&quot;\n        if session_id:\n            user += f&quot;-sid-{session_id}&quot;\n        return f&quot;http:\u002F\u002F{user}:{self.password}@{self.gateway}:{self.port}&quot;\n\n# Utilizzo combinato\npool = CountryProxyPool(&quot;user&quot;, &quot;password&quot;)\n\n@retry_with_backoff(max_retries=4, base_delay=2.0)\ndef scrape_with_pool(query: str, locale: LocaleConfig,\n                     pool: CountryProxyPool) -&gt; str:\n    proxy = pool.get_proxy(locale.country)\n    proxies = {&quot;http&quot;: proxy, &quot;https&quot;: proxy}\n    uule = build_uule(locale.canonical_place)\n    url = (f&quot;https:\u002F\u002Fwww.{locale.google_domain}\u002Fsearch?&quot;\n           f&quot;q={query}&amp;gl={locale.gl}&amp;hl={locale.hl}&quot;\n           f&quot;&amp;uule={uule}&amp;pws=0&amp;num=20&quot;)\n    headers = {\n        &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) &quot;\n                      &quot;AppleWebKit\u002F537.36 Chrome\u002F124.0.0.0 Safari\u002F537.36&quot;,\n        &quot;Accept-Language&quot;: f&quot;{locale.hl}-{locale.country}&quot;,\n    }\n    resp = requests.get(url, proxies=proxies, headers=headers, timeout=30)\n    resp.raise_for_status()\n    return resp.text\n\n# Esecuzione con retry automatico\ntry:\n    html = scrape_with_pool(&quot;restaurant&quot;, chicago, pool)\n    print(f&quot;Successo: {len(html)} byte&quot;)\nexcept RuntimeError as e:\n    logger.error(f&quot;Scraping fallito: {e}&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>Errori Comuni e Edge Case\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Parametri e IP non concordanti\u003C\u002Fstrong>: il problema più frequente. \u003Ccode>gl=US\u003C\u002Fcode> con IP tedesco produce risultati inaffidabili. Soluzione: usa sempre proxy nella stessa area dei parametri.\u003C\u002Fli>\n\u003Cli>uule malformato: il base64 deve essere dell'encoding UTF-8 del nome canonico. Nomi non inglesi (es. \"Roma\" invece di \"Rome\") non funzionano.\u003C\u002Fli>\n\u003Cli>Rate limiting aggressivo: più di 50 richieste\u002Fminuto dallo stesso IP possono innescare CAPTCHA. Usa rotazione IP e delay di 2-5 secondi tra richieste.\u003C\u002Fli>\n\u003Cli>Sticky session troppo lunga: una sessione che dura più di 30 minuti può essere flaggata. Rigenera session_id periodicamente.\u003C\u002Fli>\n\u003Cli>Ignorare robots.txt e ToS: i \u003Ca href=\"https:\u002F\u002Fwww.google.com\u002Frobots.txt\" rel=\"noopener noreferrer\">robots.txt di Google\u003C\u002Fa> e i Termini di Servizio vietano l'accesso automatizzato non autorizzato. Valuta alternative come la \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fcustom-search\u002Fdocs\u002Foverview\" rel=\"noopener noreferrer\">Google Custom Search API\u003C\u002Fa> per volumi moderati (100 query\u002Fgiorno gratuite, poi $5 per 1000 query).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Considerazioni su Dati Pubblici e ToS\u003C\u002Fh2>\n\u003Cp>Lo scraping di Google Search solleva questioni legali e etiche. I Termini di Servizio di Google proibiscono l'accesso automatizzato non autorizzato. Per dataset di produzione, considera:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>La \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fcustom-search\u002Fdocs\u002Foverview\" rel=\"noopener noreferrer\">Google Custom Search JSON API\u003C\u002Fa> ufficiale (100 query\u002Fgiorno gratuite, poi $5 per 1000 query).\u003C\u002Fli>\n\u003Cli>Rispetta il rate limiting e non sovraccaricare i server.\u003C\u002Fli>\n\u003Cli>Non raccogliere dati personali (GDPR\u002FCCPA) dai risultati SERP.\u003C\u002Fli>\n\u003Cli>Per uso commerciale su larga scala, consulta un legale esperto in data scraping.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Punti Chiave (Key Takeaways)\u003C\u002Fh2>\n\u003Cblockquote>\n\u003Cp>Il scraping SERP geo-targetato richiede tre elementi allineati: parametri URL corretti (gl, hl, uule, pws=0), IP residenziale nella stessa area geografica, e parsing robusto che gestisca CAPTCHA e cambiamenti di layout. Senza allineamento IP-parametri, i dati raccolti sono inaffidabili.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cul>\n\u003Cli>uule è essenziale per precisione a livello città — il solo \u003Ccode>gl\u003C\u002Fcode> non basta per local SEO.\u003C\u002Fli>\n\u003Cli>pws=0 elimina la personalizzazione per baseline riproducibili.\u003C\u002Fli>\n\u003Cli>Proxy residenziali su \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode> con flag \u003Ccode>-country-XX-region-rrr-city-yyy\u003C\u002Fcode> garantiscono allineamento IP-parametri.\u003C\u002Fli>\n\u003Cli>Sticky session per SERP multi-pagina: stesso IP per coerenza tra pagine.\u003C\u002Fli>\n\u003Cli>Retry con backoff su 429\u002F503 e rotazione IP per-country per evitare CAPTCHA.\u003C\u002Fli>\n\u003Cli>curl_cffi con impersonate=chrome supera i controlli TLS fingerprint meglio di requests puro.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Per approfondire, consulta la \u003Ca href=\"\u002Fit\u002Fpricing\">documentazione sui prezzi di ProxyHat\u003C\u002Fa> e i nostri \u003Ca href=\"\u002Fit\u002Fuse-cases\u002Fserp-tracking\">casi d'uso per SERP tracking\u003C\u002Fa>. La \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">documentazione ufficiale ProxyHat\u003C\u002Fa> contiene tutti i dettagli sulla configurazione avanzata dei proxy residenziali.\u003C\u002Fp>","Best Practices Scraping SERP Geo-Targetato | ProxyHat","Guida completa per scraping SERP geo-targetato: parametri uule, gl, hl, proxy residenziali e codice Python pronto. Ottimizza il rank tracking locale.","\u002Fit\u002Fblog\u002Fscraping-serp-geo-targetato-best-practices",null,"Guida completa per scraping SERP geo-targetato: parametri uule, gl, hl, proxy residenziali e codice Python pronto.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-serp-geo-targetato-best-practices-og.webp",[18,21,24],{"question":19,"answer":20},"Perché lo scraping SERP geo-targetato è importante per gli utenti proxy?","Lo scraping SERP geo-targetato è critico per gli utenti proxy perché Google cross-controlla i parametri URL con la geolocalizzazione dell'IP. Se i parametri indicano US ma l'IP è in Europa, i risultati sono inaffidabili. I proxy residenziali permettono di allineare l'IP con i parametri URL, garantendo che i dati raccolti siano accurati e riproducibili. Senza proxy localizzati, il geo-targeting tramite soli parametri URL produce risultati distorti e non rappresentativi.",{"question":22,"answer":23},"Quale tipo di proxy funziona meglio per lo scraping SERP geo-targetato?","I proxy residenziali sono la scelta ottimale per lo scraping SERP geo-targetato perché utilizzano IP di dispositivi reali assegnati da ISP locali, rendendoli indistinguibili dal traffico organico. I proxy datacenter sono facilmente identificabili e spesso bloccati da Google. I proxy mobili offrono un ulteriore livello di affidabilità ma a costi maggiori. Per la maggior parte dei casi d'uso SERP, i residenziali con targeting città offrono il miglior rapporto qualità-prezzo.",{"question":25,"answer":26},"Come evitare i blocchi nello scraping SERP geo-targetato?","Per evitare blocchi nello scraping SERP geo-targetato: usa proxy residenziali con rotazione IP per paese, mantieni un rate di massimo 50 richieste\u002Fminuto per IP, implementa retry con backoff esponenziale su HTTP 429\u002F503, usa curl_cffi con impersonazione Chrome per superare i controlli TLS fingerprint, aggiungi delay di 2-5 secondi tra richieste, e rigenera le sessioni sticky ogni 30 minuti. Rispetta sempre i Termini di Servizio della piattaforma.",false,"2026-07-31T16:11:16+00:00","2026-10-03T23:52:59+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-serp-geo-targetato-best-practices-master.webp","Geo-Targeted SERP Scraping Best Practices for Local SEO Data","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-serp-geo-targetato-best-practices-card.webp",12,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[39],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},3,"serp-seo-tracking","SERP & SEO Tracking","SERP & SEO Tracking Guide | ProxyHat Blog","Scopri come monitorare le classifiche dei motori di ricerca e raschiare i SERP con i proxy.",[],{"en":47,"x-default":47},"\u002Fblog\u002Fgeo-targeted-serp-scraping-best-practices",{"zh":49,"ja":50,"pl":51,"es":52,"it":13,"tr":53,"ko":54,"en":47,"ru":55,"de":56,"fr":57,"pt":58},"\u002Fcn\u002Fblog\u002Fserp-dili-dingwei-zhuaqu-zhinan","\u002Fja\u002Fblog\u002Fgeo-targeted-serp-scraping-guide","\u002Fpl\u002Fblog\u002Fgeotargetowane-scrapowanie-serp-najlepsze-praktyki","\u002Fes\u002Fblog\u002Fscraping-serp-geo-segmentado-mejores-practicas","\u002Ftr\u002Fblog\u002Fcografi-hedefli-serp-kazima-rehberi","\u002Fko\u002Fblog\u002Fgeo-targeted-serp-scraping-guide","\u002Fru\u002Fblog\u002Fgeo-targeted-serp-scraping-best-practices","\u002Fde\u002Fblog\u002Fgeo-targeted-serp-scraping-leitfaden","\u002Ffr\u002Fblog\u002Fscraping-serp-geocible-meilleures-pratiques","\u002Fpt\u002Fblog\u002Fpraticas-serp-scraping-geo-targeted",59,[61,78,94,111],{"id":62,"slug":63,"title":64,"excerpt":65,"featured_image_url":66,"featured_image_alt":67,"card_image_url":68,"og_image_url":69,"published_at":70,"updated_at":70,"content_updated_at":71,"reading_time_minutes":72,"is_featured":27,"indexable":4,"views":73,"author":74,"categories":75,"tags":77},155,"monitoraggio-posizionamento-keyword-amazon-proxy","Monitoraggio del Posizionamento Keyword sui Marketplace con Proxy: Guida per Sviluppatori (Esempio Amazon)","Una guida pratica in Python per monitorare il posizionamento organico dei prodotti su Amazon usando proxy residenziali, parsing del SERP e best practice di produzione.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fmonitoraggio-posizionamento-keyword-amazon-proxy-master.webp","Amazon Keyword Rank Tracking with Proxies: A Developer's Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fmonitoraggio-posizionamento-keyword-amazon-proxy-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fmonitoraggio-posizionamento-keyword-amazon-proxy-og.webp","2026-07-16T16:05:31+00:00","2026-10-04T01:29:51+00:00",13,98,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[76],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":79,"slug":80,"title":81,"excerpt":82,"featured_image_url":83,"featured_image_alt":84,"card_image_url":85,"og_image_url":86,"published_at":87,"updated_at":87,"content_updated_at":88,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":89,"author":90,"categories":91,"tags":93},153,"scraping-people-also-ask-autocomplete-python","Scraping di People Also Ask e Autocomplete di Google per ricerca keyword (guida Python)","Una guida pratica per sviluppatori ed SEO su come estrarre suggerimenti Autocomplete, domande People Also Ask e ricerche correlate da Google usando Python, httpx, Playwright e proxy residenziali geo-targetizzati.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-people-also-ask-autocomplete-python-master.webp","Scrape Google People Also Ask and Autocomplete for Keyword Research (Python Guide)","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-people-also-ask-autocomplete-python-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fscraping-people-also-ask-autocomplete-python-og.webp","2026-07-14T16:06:25+00:00","2026-10-03T08:29:54+00:00",124,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[92],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":95,"slug":96,"title":97,"excerpt":98,"featured_image_url":99,"featured_image_alt":100,"card_image_url":101,"og_image_url":102,"published_at":103,"updated_at":103,"content_updated_at":104,"reading_time_minutes":105,"is_featured":27,"indexable":27,"views":106,"author":107,"categories":108,"tags":110},154,"tracciare-brand-google-ai-overviews-1","Come Tracciare il Tuo Brand in Google AI Overviews: Guida Strategica","Google AI Overviews compare su circa il 36% delle query informative, rendendo la citation share il nuovo KPI SEO. Ecco come costruire un pipeline di monitoraggio con proxy residenziali, headless browser e governance corretta.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Ftracciare-brand-google-ai-overviews-1-master.webp","How to Track Your Brand in Google AI Overviews: A Strategic Guide for SEO & Data Teams","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Ftracciare-brand-google-ai-overviews-1-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Ftracciare-brand-google-ai-overviews-1-og.webp","2026-07-14T10:05:37+00:00","2026-10-03T08:29:51+00:00",10,66,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[109],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"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":121,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":122,"author":123,"categories":124,"tags":126},152,"costruire-rank-tracker-python-proxy","Costruire un Google Rank Tracker in Python con Proxy Residenziali","Guida pratica per sviluppatori: costruisci un rank tracker Google in Python usando proxy residenziali, curl_cffi e SQLite. Include rotazione IP, geo-targeting e gestione CAPTCHA.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fcostruire-rank-tracker-python-proxy-master.webp","Build a Google Rank Tracker in Python with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fcostruire-rank-tracker-python-proxy-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fit\u002Fcostruire-rank-tracker-python-proxy-og.webp","2026-07-02T16:04:58+00:00","2026-10-03T23:53:00+00:00",56,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[125],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],[]]