[{"data":1,"prerenderedAt":108},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fproxies\u002Fvercel":3},{"page":4,"toc":92,"updated":107},{"path":5,"title":6,"seoTitle":7,"description":8,"blocks":9},"\u002Fdocs\u002Fproxies\u002Fvercel","Vercel proxy","Vercel First-Party Proxy for the Browser SDK","A dependency-free Routing Middleware file for any project on Vercel: it answers the one path the dashboard issued and forwards the browser SDK's calls to Fingerly.",[10,13,17,22,75,78,80,83,86,88,90],{"type":11,"text":12},"p","A Routing Middleware file for any project on Vercel, whatever its framework. It answers one path the dashboard issued, on your own domain, and forwards only the browser SDK's submissions to Fingerly. It is not an open proxy: the upstream is a constant in the code, and every other path and method is refused. Version 1.0.0.",{"type":14,"tone":15,"text":16},"callout","tip","On Next.js, a route handler leaves your own middleware alone: `app\u002Fk7x2qm4a\u002Froute.ts` exporting `POST` from [`createProxy`](\u002Fdocs\u002Fsdks\u002Fnode#serve-the-browser-sdk-from-your-domain) in `@fingerly\u002Fnode`. Choose **Your application** as how it runs.",{"type":18,"level":19,"text":20,"id":21},"heading",2,"Set up","set-up",{"type":23,"steps":24},"steps",[25,32,45,56,65],{"title":26,"blocks":27},"Create the proxy",[28,30],{"type":11,"text":29},"In the dashboard, open **Integration > Proxy keys** and choose **New proxy**. Pick the environment of the public key it will forward, and **Vercel** under **How it runs**. Copy the [proxy key](\u002Fdocs\u002Fproxy-integrations#proxy-keys) it shows once, and note the path it issued, such as `\u002Fk7x2qm4a`.",{"type":11,"text":31},"The dashboard then prints the steps below, filled in with your proxy's own path and key. They stay under **Show setup** in the proxy's menu, without the key, which is never shown again.",{"title":33,"blocks":34},"Add middleware.ts",[35,37],{"type":11,"text":36},"Save `middleware.ts` at the root of your project, beside `package.json`. It has no dependencies, only the web-standard `Request` and `Response`. The path appears twice, in `config.matcher` and in `PATH`, and both must hold yours; the dashboard prints the file with them filled in.",{"type":38,"samples":39},"code",[40],{"label":41,"lang":42,"code":43,"check":44},"middleware.ts","ts","export const config = { matcher: '\u002Fk7x2qm4a' }\n\n\u002F** The path the dashboard issued. Keep it equal to the matcher above. *\u002F\nconst PATH = '\u002Fk7x2qm4a'\n\u002F\u002F ... the rest of the file, as the dashboard prints it",false,{"title":46,"blocks":47},"Add the proxy key",[48,50],{"type":11,"text":49},"As a sensitive environment variable, or in the project's **Settings > Environment Variables**.",{"type":38,"samples":51},[52],{"label":53,"lang":54,"code":55},"Terminal","bash","vercel env add FINGERLY_PROXY_KEY production --value \"fly_px_production_…\" --sensitive --yes",{"title":57,"blocks":58},"Deploy",[59,61],{"type":11,"text":60},"The middleware runs from the next production deployment.",{"type":38,"samples":62},[63],{"label":53,"lang":54,"code":64},"vercel deploy --prod",{"title":66,"blocks":67},"Point the browser SDK at the path",[68,73],{"type":38,"samples":69},[70],{"label":71,"lang":42,"code":72},"fingerly.ts","import { load } from '@fingerly\u002Fweb-js'\n\nconst fingerly = await load({\n  apiKey: 'fly_pk_production_…',\n  endpoints: '\u002Fk7x2qm4a',\n})",{"type":11,"text":74},"The SDK posts both of its calls to the path exactly as given. Once pages use it, the proxy's row in **Proxy keys** shows it last seen, running `vercel\u002F1.0.0`, with its requests over the last 30 days.",{"type":18,"level":19,"text":76,"id":77},"How the visitor's address is trusted","how-the-visitor-s-address-is-trusted",{"type":11,"text":79},"The middleware sends `x-real-ip` as `x-fingerly-client-ip`, falling back to the first `x-forwarded-for` entry. Vercel sets both itself, and overwrites `x-forwarded-for` with the client's address rather than passing on what the visitor sent, so on Vercel neither can be forged.",{"type":14,"tone":81,"text":82},"warning","Do not reuse this code on a platform that passes those headers through from the visitor.",{"type":18,"level":19,"text":84,"id":85},"What it sends and relays","what-it-sends-and-relays",{"type":11,"text":87},"Upstream, to `https:\u002F\u002Fapi.fingerly.io\u002Fapi\u002Fv1\u002Fingest` and nowhere else, on headers built from scratch: `content-type`, `x-api-key`, `Idempotency-Key` when present, and the `x-fingerly-*` headers the proxy sets itself (the proxy key, the visitor's address, the page origin, the user agent and `x-fingerly-proxy-version: vercel\u002F1.0.0`). Cookies, `Authorization` and any `x-fingerly-*` header a visitor sends never leave.",{"type":11,"text":89},"Other methods answer `405` with `Allow: POST`, and other paths `404`. Bodies over 1 MiB are refused with `413`, redirects are not followed, and a missing or malformed key answers `503` rather than forwarding anything.",{"type":11,"text":91},"Back to the page: the API's status and body, with only `content-type`, `x-request-id`, `ratelimit-limit`, `ratelimit-remaining` and `retry-after`, plus `cache-control: no-store`. Nothing relayed names Fingerly.",[93,94,97,99,101,103,105,106],{"id":21,"text":20,"level":19},{"id":95,"text":26,"level":96},"step-create-the-proxy",3,{"id":98,"text":33,"level":96},"step-add-middleware-ts",{"id":100,"text":46,"level":96},"step-add-the-proxy-key",{"id":102,"text":57,"level":96},"step-deploy",{"id":104,"text":66,"level":96},"step-point-the-browser-sdk-at-the-path",{"id":77,"text":76,"level":19},{"id":85,"text":84,"level":19},"2026-09-25T18:31:31.000Z",1793630453188]