Traditional web scrapers are brittle: you write CSS selectors or XPath to pull each field, and the moment a site tweaks its markup, your script breaks. Large language models like Google Gemini change that. Instead of hard-coding where the data lives, you describe what you want in plain English and let the model read the page semantically. This guide shows two practical ways to scrape with Gemini in Python, how to keep your token bill down, and why residential proxies are still the part you cannot skip.
Why Use Gemini for Web Scraping?
LLM-assisted scraping trades fragile selectors for semantic understanding. The wins are real:
- Resilient to layout changes. Gemini reads meaning, not tags, so a redesign that renames classes rarely breaks your extraction.
- Structured output on demand. Ask for JSON with specific keys and you get clean, typed data ready for a database or CSV.
- Handles messy pages. Inconsistent formatting, mixed languages, and free-text fields that would need dozens of edge-case rules are handled in one prompt.
- Fast to build. A working extractor is a prompt plus a few lines of Python, not an afternoon of inspecting the DOM.
It is the same shift we covered for other models — see web scraping with Claude and how to use ChatGPT for web scraping. Gemini's advantage is a generous free tier, strong long-context handling, and a built-in tool that can fetch pages for you.
Two Ways to Scrape With Gemini
There are two paths, and picking the right one is most of the battle:
- The URL Context tool — Gemini fetches the page itself from a URL you provide. Zero fetching code, great for simple public pages.
- Fetch the HTML yourself — you download the page with
requestsor Playwright (through a proxy), then hand the cleaned text to Gemini. More code, but the only option for protected, geo-restricted, or JavaScript-heavy sites.
The URL Context Tool: Let Gemini Fetch the Page
Gemini can retrieve a handful of public URLs per request and answer questions about them directly. With the current google-genai SDK it looks like this:
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents=(
"From https://example.com/product/1 extract the product name, "
"price and rating. Return only JSON with keys name, price, rating."
),
config=types.GenerateContentConfig(
tools=[types.Tool(url_context=types.UrlContext())],
),
)
print(resp.text)
This is the fastest way to prototype. The catch: Gemini fetches from Google's own servers, so it only works on simple, public, static pages. Anything behind a login, a paywall, aggressive anti-bot protection, or heavy client-side JavaScript will return an error or an empty page — and you cannot control the exit IP or location. For those targets, you fetch the HTML yourself.
When You Need to Fetch the HTML Yourself
You take over fetching whenever the target is hardened or dynamic:
- Anti-bot systems (Cloudflare, DataDome, PerimeterX) that block datacenter IPs and unfamiliar clients.
- Geo-restricted content where prices, catalogs, or results depend on the visitor's country.
- JavaScript-rendered pages that need a real browser (Playwright) to load the data.
- Rate limits that require spreading requests across many IPs.
All four are solved the same way: route your requests through residential proxies so each looks like an ordinary user browsing from a real home connection, then pass the finished HTML to Gemini.
Setup: API Key and Client
Grab a free API key from Google AI Studio, then install the SDK and helpers:
python -m venv venv
source venv/bin/activate
pip install google-genai requests beautifulsoup4
Gemini offers several models. For scraping, gemini-2.5-flash is the sweet spot — fast, cheap, and more than capable of pulling fields out of a page. Reserve the larger pro models for genuinely complex reasoning.
Preparing HTML to Save Tokens
Feeding raw HTML straight to Gemini is the most common mistake. Markup, inline scripts, and styles can be 90% of a page's bytes and burn through your token limit for nothing. Strip the page down to visible text first with BeautifulSoup:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
for tag in soup(["script", "style", "nav", "footer", "svg", "noscript"]):
tag.decompose()
text = soup.get_text(" ", strip=True)
This routinely cuts payload size by 80% or more, which means lower cost and faster responses. For very long pages, truncate to the section you care about before sending.
Extracting Structured Data With Gemini
The reliability trick is to force JSON output with response_mime_type so you never have to parse loose prose or strip code fences. Here is the full manual pipeline — fetch through a SpyderProxy residential proxy, clean, extract, and load into a Python dict:
import json
import requests
from bs4 import BeautifulSoup
from google import genai
from google.genai import types
proxy = "http://USERNAME:[email protected]:12321"
proxies = {"http": proxy, "https": proxy}
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
# 1. fetch the page through a residential proxy
html = requests.get("https://example.com/product/1", proxies=proxies, timeout=20).text
# 2. strip boilerplate so tokens are spent on content, not markup
soup = BeautifulSoup(html, "html.parser")
for tag in soup(["script", "style", "nav", "footer", "svg", "noscript"]):
tag.decompose()
text = soup.get_text(" ", strip=True)[:12000]
# 3. let Gemini pull structured fields out of the cleaned text
prompt = (
"Extract the product name, price (number only) and rating from this page text. "
"Return JSON with keys name, price, rating.\\n\\n" + text
)
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents=prompt,
config=types.GenerateContentConfig(response_mime_type="application/json"),
)
data = json.loads(resp.text)
print(data)
Because the proxy IP is a real residential address, the target sees an ordinary visitor and returns the full page — the same reason residential proxies are the default for web scraping and AI data collection.
Saving and Reusing Scraped Data
Once Gemini returns structured records, persist them. JSON keeps nested fields intact; CSV is cleaner for flat, tabular data headed to a spreadsheet or analytics (see JSON vs CSV). A common pattern is to scrape to JSON to preserve everything, then export a flattened CSV for analysis — useful when you are building datasets for machine learning.
Scaling Up: Loop, Rotate, Retry
To run across thousands of pages, wrap the pipeline in a loop, rotate IPs, and add retries with backoff. Rotating residential proxies give you a fresh IP per request automatically, so no single address gets rate-limited or banned. Keep Gemini calls batched sensibly to stay under model rate limits, and cache pages you have already fetched so a re-run does not pay twice. For the fundamentals of a resilient collector, see how to build a web scraper in Python.
Limitations, Anti-Bot Defenses, and Cost
- It is not free at scale. Every page is tokens in and tokens out. Clean your HTML, truncate, and use
flashmodels to keep costs sane. - Models can hallucinate. For high-stakes data, validate the JSON against a schema and spot-check results rather than trusting blindly.
- Rate limits apply on both the Gemini API and the target site — space out requests and rotate IPs.
- The LLM does not defeat blocks. Gemini reads pages; it does not get you past anti-bot walls. That is the proxy's job.
Gemini is a superb parser. The fetching — looking like a real user, from the right country, at scale — is still the hard part, and it is exactly what a good residential network handles.
Frequently Asked Questions
Can Gemini fetch web pages on its own?
Yes, via the URL Context tool, which retrieves a small number of public URLs per request. It only works on simple, public, static pages — anything behind a login, paywall, anti-bot system, or heavy JavaScript needs you to fetch the HTML yourself, ideally through a residential proxy.
Do I still need proxies if I use Gemini?
For anything beyond a few simple public pages, yes. Gemini parses content but does not disguise your requests. To fetch protected, geo-restricted, or rate-limited pages at scale without being blocked, you route requests through residential proxies so each looks like a real user.
Which Gemini model is best for scraping?
gemini-2.5-flash is the practical default — fast, inexpensive, and accurate at extracting fields from cleaned page text. Save the larger pro models for tasks that need heavy reasoning, since they cost more per page.
How do I stop Gemini from wasting tokens on HTML?
Strip scripts, styles, and navigation with BeautifulSoup and send only the visible text, truncated to the relevant section. This commonly cuts payload by 80% or more, lowering cost and speeding up responses.
Is scraping with Gemini legal?
Using Gemini to parse pages does not change the rules. Scrape only public data, respect robots.txt and terms of service, avoid login-gated content you are not authorized to access, and comply with privacy laws for any personal data. The legality depends on the site and your jurisdiction, not the tool.
Conclusion
Gemini turns web scraping from a selector-maintenance chore into a describe-what-you-want workflow: fetch a page, strip it to text, and let the model return clean JSON. Use the URL Context tool for quick public pages, and fetch the HTML yourself through residential proxies for everything hardened, geo-locked, or dynamic. The model handles the parsing; the proxy handles the access.
Feed your Gemini scraper pages it can actually reach: SpyderProxy residential proxies from $2.75/GB — ethically sourced, 195+ countries, built to beat blocks and rate limits.