Fetch any public URL as a visitor in a chosen country, with a signed receipt of its origin.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Pre-release. Neither package is published to npm yet, so the install commands below do not work today β build from source (see Development). The hosted API at
regionfetch.devis live.
Fetch a public HTTPS URL as a visitor in a specific country would see it, and get a signed receipt proving where the retrieval actually came from.
One request. One x402 payment. One Ed25519-signed attestation of the exit country, supplier, final URL, and content hash.
This repository holds the public client packages:
| Package | npm | What it is |
|---|---|---|
regionfetch | npm i regionfetch | TypeScript SDK β fetch, recover, verify |
regionfetch-mcp | npx regionfetch-mcp | MCP server exposing one regionfetch tool |
The service itself runs at https://regionfetch.dev.
Countries: US, DE, JP, BR, IN. Anything else is rejected locally before a payment is created.
| Mode | What it does |
|---|---|
http (default) | Direct proxied GET with a country-appropriate locale, user agent, and Accept-Language. Follows up to five redirects, revalidating each target. |
browser | Headless Chromium through the regional proxy, with a country-appropriate locale, timezone, viewport, and user agent. Waits for domcontentloaded and returns rendered HTML. |
max_tier caps how hard the service will work to retrieve a blocked page:
L0 and L1 use the standard regional supplier, L2 permits escalation to a
managed unblocker and costs more. Defaults to L1.
The client never assumes a price β it authorizes exactly the amount the
deployment returns in its challenge, so a dearer tier needs no client change.
L3 is not a supported capability and is rejected before any payment is
created.
L2 is priced higher than L0/L1 β $0.05 against $0.02 at the time of writing β and the price comes from the challenge, never from the client.
The default list price is $0.02 USDC per request on Base
(eip155:8453). Price, network, timeout, and response-size limits are
deployment-controlled β read them from the 402 challenge rather than hardcoding
them.
@x402/* packages, not x402 or x402-fetchThis matters more than it looks. The deployment speaks x402 protocol v2:
eip155:8453), not chain names (base)amount field, not maxAmountRequiredPAYMENT-REQUIRED response header, with an empty bodyPAYMENT-SIGNATURE request header, not X-PAYMENTThe unscoped x402 and x402-fetch packages on npm are v1 only. They parse
the challenge from the response body, hardcode x402Versions = [1], reject a
CAIP-2 network at the schema, and send X-PAYMENT. They cannot pay this API.
Install the v2 stack:
The SDK sends one unpaid probe, reads the challenge from the header, asks the provider for exactly one authorization, and retries once. It will never mint a second payment for one logical fetch β if the paid attempt is still refused, you get an error rather than a second charge.
One authorization funds one durable request. Reusing it for a different body is rejected. Resending the identical body with the identical authorization after a dropped connection is the correct recovery β see below.
paymentProvider is a one-method interface, so you are not tied to viem or to
any particular custody model:
Every terminal outcome β success and paid failure β carries a signed receipt.
Four independent checks, because a valid signature alone proves less than it appears to:
| Check | What it rules out |
|---|---|
signatureValid | Tampering with the signed bytes |
payloadMatches | A payload edited after signing, leaving payloadCanonical intact |
receiptFieldsMatch | Convenience fields at the receipt root disagreeing with what was signed |
bodyHashMatches | A body swapped in transit |
keyMatchesExpectation | A self-consistent receipt minted with someone else's key |
Two things the implementation is strict about:
payloadCanonical verbatim. Re-serializing
attestation.payload can produce different bytes and either fails spuriously
or, worse, masks a mismatch.attestation.algorithm is
attacker-controlled text; an RSA key presented as "Ed25519" is rejected.Without a pinned or independently retrieved key, verification proves internal
consistency only β anyone can mint a self-consistent receipt with their own key.
Pass expectedKeyId / expectedPublicKeyPem when you need origin trust.
| Status | Meaning | What the SDK does |
|---|---|---|
400 | Invalid body, country, mode, or target | Throws. Do not retry unchanged. |
402 | Payment absent or unverified | Throws RegionFetchPaymentRequiredError with the decoded challenge |
409 | Same payment already processing | Retries the identical request with the same authorization |
429 | Rate limited | Retries with exponential backoff, honouring Retry-After |
502 / 504 | Terminal paid failure | Throws with the signed receipt attached. Never retried. |
503 | Service or dependency unavailable | Throws. Not retried by default. |
Default policy: two retries, exponential backoff with jitter, Retry-After
respected. Configure with retry: { maxRetries, baseDelayMs, maxDelayMs }.
If the connection drops after you sent a payment, do not create a second
payment β but be aware that resending the identical authorization will not
recover the result either. x402 exact uses EIP-3009, whose nonce is spent
on-chain at settlement, so a settled payment is refused with 402 rather than
replayed. Resending is harmless (it cannot charge twice), it just will not work.
The reliable recovery is the status endpoint, so capture requestId from
every response you do receive:
state.status | Meaning |
|---|---|
succeeded / failed | Terminal. A stored failure arrives as HTTP 200, with the detail in the receipt. |
settling / executing | Still in flight. |
unresolved | Execution may have happened but was never persisted. The server will not re-run it β that could duplicate an external effect after payment. Reconcile against the settlement transaction. |
The deployment's payment gate runs ahead of body validation: an unpaid
request with country: "ZZ" still answers 402, not 400. So the SDK validates
input before touching the network β otherwise you would mint an authorization
for a request the server then rejects.
Checked locally: HTTPS-only, URL length β€ 2048, known country, known mode, no unknown fields, and obvious loopback/private targets. The server remains authoritative for DNS resolution and the real public-target policy.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/region-fetch)<a href="https://allmcps.com/mcp/region-fetch"><img src="https://allmcps.com/api/badge/region-fetch?style=directory" alt="Region Fetch on AllMCPs" /></a>