geizhals-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@geizhals-mcpsearch for the cheapest RTX 4070"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
geizhals-mcp
An MCP server that lets an LLM search Geizhals, a leading German/DACH price-comparison site, for the cheapest offers on new products. Built for self-hosting: one container, no API keys, no per-query credits.
Companion to jnslmk/kleinanzeigen-mcp — that one covers second-hand classifieds, this one covers new retail goods.
Geizhals search pages sit behind a Cloudflare JS challenge, so
search_productsandsearch_by_urldrive a real (patched, headed) browser. Product detail and price-history calls use direct HTTP; product detail parses the server-rendered offer table while price history preserves the endpoint data. Search parsing is anchored on the livegalleryview__*markup. These paths were verified end-to-end against live pages (July 2026).Note on sorting: the default
relevancesort returns the products you searched for.sort=priceasks Geizhals for cheapest-first across its broad free-text match, which for loose queries surfaces cheap loosely-related items — prefer it only with a specific query.
Tools
Tool | What it does |
| Search by keyword, sort by price/relevance, filter by price band. Returns product summaries. |
| Full detail — name, price range, per-merchant offers — for one product id. |
| Full details for several ids at once — the normal follow-up to a search. |
| Direct, cookieless price history for one product id and a fixed period/location. |
| Search from a pasted Geizhals URL, preserving filters |
The intended flow is search_products → pick interesting ids →
get_products_batch. Search results omit the per-merchant offer tables so a
broad search does not blow up the model's context window.
Related MCP server: ssc
How it works
Geizhals search pages are fronted by Cloudflare's "Sichere Verbindung wird überprüft" JS challenge, which returns 403 to a plain HTTP client. So:
Search browser: patchright (a patched, undetected Playwright fork) drives Chromium headed under Xvfb for
search_productsandsearch_by_url— a headed browser behind a virtual display clears Cloudflare far more reliably than headless from a datacenter IP.Direct HTTP:
get_productandget_products_batchparse server-rendered offer tables, whileget_price_historyPOSTs directly to the cookieless price-history endpoint.Parsing:
scraper.pyreadsgalleryview__*search tiles and the stableaNNNNNNN.htmlproduct hrefs.
Running it
docker run --rm -p 8000:8000 --shm-size=1g ghcr.io/jnslmk/geizhals-mcp:latestStreamable HTTP at http://localhost:8000/mcp, plain GET /healthz for
container healthchecks. Give the container at least 1.5 GB of memory and
--shm-size=1g — Chromium maps its renderer heap into /dev/shm.
Configuration
Variable | Default | Purpose |
|
|
|
|
| Bind address |
|
| Bind port |
|
| MCP endpoint path |
|
| Concurrent browser search navigations (hard-capped at 2) |
|
| Hard cap on products returned by a search |
|
| Cap on ids per |
|
| How long to wait for a search-page Cloudflare challenge to clear |
|
| Browser search attempts after a challenge or 429 rate limit (hard-capped at 3) |
|
| Minimum delay between browser search navigations |
|
| Upper bound for browser-search retry backoff |
| recent Chrome UA | Browser search user agent; override when the built-in default ages |
|
| Pause browser searches after all challenge attempts fail |
|
|
|
| (none) | Search-browser egress proxy URL, e.g. |
| (none) | Optional search-browser proxy auth |
|
| Python log level |
LibreChat
mcpServers:
geizhals:
type: streamable-http
url: "http://geizhals-mcp:8000/mcp"
timeout: 180000
chatMenu: true
mcpSettings:
allowedAddresses:
- "geizhals-mcp:8000"allowedAddresses is required — LibreChat's SSRF guard blocks MCP URLs that
resolve to private addresses, which a sibling container always does. The timeout
is generous because a cold search call starts a browser and may wait through a
Cloudflare challenge or the configured request pacing.
Claude Code
claude mcp add --transport http geizhals http://localhost:8000/mcpDevelopment
uv venv && uv pip install -e .
patchright install chromium
# Headless is fine for a quick check; headed (default) needs a display:
GH_HEADLESS=1 python -m geizhals_mcpThe scraper intentionally stays low-volume. Each browser search navigation
passes through one shared request gate, with a jittered minimum interval between
starts; pages on the shared browser context remain capped by
GH_MAX_CONCURRENT. A challenge or 429 rate limit gets at most
GH_MAX_ATTEMPTS attempts, with bounded exponential backoff
(GH_BACKOFF_CAP_SECONDS, honoring the server's Retry-After) in between. If
all attempts are blocked, the process enters a shared
GH_CLOUDFLARE_COOLDOWN_SECONDS cooldown: later search calls fail immediately
with an explicit error that includes an approximate retry delay, rather than
starting another challenge timeout. No proxy rotation, challenge bypass, or
stale-result cache is performed.
To verify a release:
Run the server and call
search_productswith a common term (e.g.RTX 4070).If results come back empty but the logs show no Cloudflare block, the row selectors in
_SELare stale — capture a real search page (page.content()), inspect it, and correct_SEL["row"],_SEL["row_price"]and_SEL["row_offercount"].If
get_productfails, inspect its direct HTTP response and the server-rendered offer table parser.If a search call reports a Cloudflare cooldown or challenge failure, wait for the stated delay before trying again. Repeated calls during that window are rejected locally and do not send more browser requests.
Cloudflare and proxies
Cloudflare challenges are much harsher on datacenter IPs — in practice they
will not clear from a typical VPS. Route browser search traffic through a
residential IP by setting GH_PROXY to an HTTP proxy that egresses from one
(for a self-hosted setup, a small proxy on a home box reachable over a
VPN/tailnet works well):
docker run --rm -p 8000:8000 --shm-size=1g \
-e GH_PROXY=http://192.168.1.10:8888 \
ghcr.io/jnslmk/geizhals-mcp:latestbrowser.py passes it straight to chromium.launch(proxy=…) for browser
searches. From a residential IP no proxy is needed.
Images
ghcr.io/jnslmk/geizhals-mcp — multi-arch (linux/amd64, linux/arm64), built
by GitHub Actions on native runners for each architecture.
Tag | Meaning |
| Newest build of |
| A specific commit |
| Release tags |
Caveats
Geizhals has no public API: search pages require a browser, while product detail pages and the cookieless price-history endpoint use direct HTTP. These paths can break whenever Geizhals change their markup, endpoint, or Cloudflare policy, and heavy or parallel use will trip bot detection — particularly from a datacenter IP. Scraping is also at odds with Geizhals' terms of service. Keep it to personal-scale use; the conservative browser search defaults exist for exactly this reason.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Capability registry for the agentic economy. Semantic search over verified MCP server listings.
MCP server for AI dialogue using various LLM models via AceDataCloud
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Related MCP Servers
- AlicenseCqualityCmaintenanceA Model Context Protocol server enabling product searches across e-commerce platforms, price history tracking, and product specification-based searches using natural language prompts.248 PyPI19MIT

sscofficial
AlicenseNot gradedqualityDmaintenanceMCP server for scraping product prices, offers, reviews, and details from Amazon, Google Shopping, Bol.com, and Coolblue via natural language commands, with spend-cap protections.4 npm1MIT- AlicenseBqualityBmaintenanceMCP server for finding, comparing, and ranking the cheapest real offers across eBay, Amazon, Craigslist, OfferUp, and Google Shopping, with tax estimation and exact-model filtering.6MIT
- AlicenseAqualityAmaintenanceAn MCP server that lets an LLM search and inspect eBay listings through the official Browse API.2MIT