Vercel Static IP for Functions: Setup and Cost
Vercel Functions send traffic from a shared, changing pool of cloud IPs, so a partner cannot allowlist them. Vercel sells Static IPs for $100 per project per month on Pro and Enterprise, plus data transfer. Fixedmark routes the calls that need a fixed address through a proxy URL instead, so one dedicated IP pair can serve every project and every platform you deploy to.
Why Vercel's outbound IP changes
Vercel runs your functions on managed compute in the regions you select. Each invocation can land on a different instance, and those instances share a large pool of provider IP addresses with other Vercel customers. Vercel does not publish a fixed list of egress IPs for regular deployments, and the address your function used yesterday is not guaranteed today.
That is fine for public APIs. It breaks when the other side checks the source IP: a MongoDB Atlas access list, a bank payout API, a broker's order API, a customer's firewall, or GitHub Enterprise with IP allow lists. Allowlisting 0.0.0.0/0 defeats the point, and allowlisting a cloud provider's published ranges lets in everyone else on that cloud.
Vercel Static IPs: what it costs
Vercel's own answer is Static IPs. Per Vercel's docs, it is available on Pro and Enterprise plans and costs $100 per project per month, plus Private Data Transfer at regional rates of $0.15 to $0.31 per GB. Each configured region gets its own static IP pair, for up to 3 regions per project. The IPs come from a VPC shared by a small group of customers and cover outbound traffic only. Routing Middleware does not use them. Dedicated, isolated networking is Secure Compute, an Enterprise feature with custom pricing.
If you have one Vercel project on Pro and want zero client code, Static IPs is the simplest route and keeps billing in one place. It gets expensive when you have several projects that call the same partner, because the fee is per project, and it does not help the parts of your stack that run elsewhere.
Sources for Vercel pricing
Checked October 2026. Confirm current details on the vendor's site before you decide. Prices and limits change.
- Vercel docs: Static IPs
- Vercel docs: Regional pricing (Private Data Transfer)
- Vercel KB: Can I get a fixed IP address?
Set up a static IP on Vercel
You route only the requests that need a fixed IP. Everything else, including Vercel's own platform calls, stays direct.
Fixedmark is in early access. Proxy URLs are issued at launch. Join early access to get yours when your region opens.
Before you start
- A Vercel project with at least one function on the Node.js, Python, or Go runtime. Any plan works, including Hobby.
- A Fixedmark proxy URL (
https://APP_ID:TOKEN@mum.egress.fixedmark.com:443) and the two IPs of your pair. Both are issued at launch. Join early access to get them. - The Vercel CLI (
npm i -g vercel) if you want to set variables from the terminal. - Access to the partner's or database's allowlist, or a contact who can add two IPv4 addresses for you.
Steps
- 1Pick a region close to your function regionChoose the Fixedmark region nearest your Vercel function region (for example Mumbai for
bom1, Frankfurt forfra1, Virginia foriad1). This keeps the extra hop short. - 2Store the proxy URL as an environment variableRun
vercel env add FIXEDMARK_PROXY_URL productionand paste the URL when prompted. Repeat forpreviewif previews call the partner. Production and preview variables are sensitive by default, so the value is hidden after you save it. Redeploy so functions pick it up. - 3Use the Node.js runtime for the calling functionThe Edge runtime's
fetchcannot use a proxy. Any route handler, API route, or server action that calls an allowlisted API must run on the Node.js runtime, which is the default. Python and Go functions work as shown below. - 4Pass the proxy to your HTTP clientIn Node.js, install
undici, importfetchandProxyAgentfrom it, and pass the agent asdispatcher. Create the agent at module scope so warm invocations reuse the connection. - 5Verify, then allowlist both IPsRun the IP check below from a deployed function. When it prints a Fixedmark IP, send both IPs of your pair to the partner.
// npm install undici (undici 8 needs Node.js 22.19+)
import { fetch, ProxyAgent } from "undici";
// FIXEDMARK_PROXY_URL=https://APP_ID:TOKEN@mum.egress.fixedmark.com:443
const proxy = new ProxyAgent(process.env.FIXEDMARK_PROXY_URL);
const res = await fetch("https://api.partner.example/v1/orders", {
dispatcher: proxy,
headers: { authorization: `Bearer ${process.env.PARTNER_API_KEY}` },
});
console.log(res.status, await res.json());# pip install requests (urllib3 1.26+ for an https:// proxy URL)
import os
import requests
proxy = os.environ["FIXEDMARK_PROXY_URL"]
proxies = {"http": proxy, "https": proxy}
res = requests.get(
"https://api.partner.example/v1/orders",
proxies=proxies,
headers={"Authorization": f"Bearer {os.environ['PARTNER_API_KEY']}"},
timeout=15,
)
print(res.status_code, res.json())package main
import (
"fmt"
"net/http"
"net/url"
"os"
"time"
)
func main() {
proxyURL, err := url.Parse(os.Getenv("FIXEDMARK_PROXY_URL"))
if err != nil {
panic(err)
}
client := &http.Client{
Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
Timeout: 15 * time.Second,
}
res, err := client.Get("https://api.partner.example/v1/orders")
if err != nil {
panic(err)
}
defer res.Body.Close()
fmt.Println(res.Status)
}SDKs that do not use fetch (the Stripe and Salesforce Node SDKs, got, axios) accept an HTTP agent. Pass new HttpsProxyAgent(process.env.FIXEDMARK_PROXY_URL) from the https-proxy-agent package, which supports https:// proxy URLs. With axios, also set proxy: false so it does not apply its own proxy logic. undici 8 needs Node 22.19 or later. On older Node, install undici@7.
Verify the egress IP on Vercel
Check the IP before you send it to a partner. Run curl locally after vercel env pull to test the credentials. Then deploy a temporary route with the Node.js check to test the deployed code path. The endpoint https://fixedmark.com/api/ip returns the caller's IP as plain text, and the What's my IP tool shows the same thing in a browser.
The proxied call should print one of your two Fixedmark IPs every time. The direct call should print a different address. If both print the same platform IP, the client is not using the proxy.
# Needs curl 7.52 or later for an https:// proxy URL.
# Prints the IP the destination sees. Run it a few times:
# you should only ever see the two IPs of your pair.
curl -sS --proxy "$FIXEDMARK_PROXY_URL" https://fixedmark.com/api/ip
# Same check over SOCKS5, the path database drivers use.
curl -sS --proxy "$FIXEDMARK_SOCKS_URL" https://fixedmark.com/api/ip
# Without the proxy, for comparison. This is the platform's own IP.
curl -sS https://fixedmark.com/api/ip// A temporary route or script that reports the egress IP.
// Remove it after you have checked.
import { fetch, ProxyAgent } from "undici";
const proxy = new ProxyAgent(process.env.FIXEDMARK_PROXY_URL);
const viaProxy = await fetch("https://fixedmark.com/api/ip", { dispatcher: proxy });
const direct = await fetch("https://fixedmark.com/api/ip");
console.log({
fixedmark: (await viaProxy.text()).trim(),
platform: (await direct.text()).trim(),
});import os
import requests
proxy = os.environ["FIXEDMARK_PROXY_URL"]
via = requests.get("https://fixedmark.com/api/ip", proxies={"https": proxy}, timeout=10)
direct = requests.get("https://fixedmark.com/api/ip", timeout=10)
print({"fixedmark": via.text.strip(), "platform": direct.text.strip()})Databases: Postgres, MySQL, and MongoDB
Vercel functions cannot run a background process, so the bm tunnel CLI is not an option there. Use a driver that can dial through SOCKS5 with FIXEDMARK_SOCKS_URL. The MongoDB Node.js driver supports this with its proxyHost, proxyPort, proxyUsername, and proxyPassword options (install the socks package next to it). Go's pgx accepts a SOCKS5 dialer through DialFunc.
node-postgres, mysql2, and psycopg have no SOCKS5 option. For those, move the queries into a small long-running service on a platform that can run bm tunnel, or use your database provider's HTTP API through the HTTPS proxy. Connection setup costs more with a proxy hop: open the client once per function instance, not per request.
- MongoDB Atlas: add both Fixedmark IPs to the project's IP Access List. See MongoDB Atlas allowlisting.
- AWS RDS, Cloud SQL, and self-hosted Postgres or MySQL: see Postgres and MySQL allowlists.
// npm install mongodb socks
import { MongoClient } from "mongodb";
// FIXEDMARK_SOCKS_URL=socks5h://APP_ID:TOKEN@mum.egress.fixedmark.com:1080
const socks = new URL(process.env.FIXEDMARK_SOCKS_URL);
const client = new MongoClient(process.env.MONGODB_URI, {
proxyHost: socks.hostname,
proxyPort: Number(socks.port),
proxyUsername: decodeURIComponent(socks.username),
proxyPassword: decodeURIComponent(socks.password),
});
await client.connect();import (
"context"
"net/url"
"os"
"github.com/jackc/pgx/v5/pgxpool"
"golang.org/x/net/proxy"
)
func connect(ctx context.Context) (*pgxpool.Pool, error) {
u, err := url.Parse(os.Getenv("FIXEDMARK_SOCKS_URL"))
if err != nil {
return nil, err
}
pw, _ := u.User.Password()
dialer, err := proxy.SOCKS5("tcp", u.Host,
&proxy.Auth{User: u.User.Username(), Password: pw}, proxy.Direct)
if err != nil {
return nil, err
}
cfg, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL"))
if err != nil {
return nil, err
}
cfg.ConnConfig.DialFunc = dialer.(proxy.ContextDialer).DialContext
return pgxpool.NewWithConfig(ctx, cfg)
}Common errors and fixes
process.env.FIXEDMARK_PROXY_URL is undefined
Variables apply only to new deployments. Redeploy after adding it, and check it is set for the environment you are testing (production, preview, or development).
Works locally, fails in a route marked runtime = 'edge'
Edge functions cannot load undici or set a proxy. Remove the edge runtime export from that route.
407 Proxy Authentication Required
The proxy did not get valid credentials. Check that the env var holds the full URL with APP_ID:TOKEN@, with no quotes or trailing newline. If the token contains @, :, or /, URL-encode it. Some clients drop credentials from the URL: pass them separately (Deno's basicAuth, axios proxy.auth) or switch to undici's ProxyAgent, which reads them from the URL.
TLS errors to the proxy: wrong version number, EPROTO, Proxy CONNECT aborted, or unable to connect to proxy
The client does not support an https:// proxy URL and is speaking plain HTTP to port 443. Upgrade it: curl 7.52+, urllib3 1.26+ (requests), httpx 0.26+, undici ProxyAgent, Go 1.10+. In Ruby, use Typhoeus: Net::HTTP and Faraday's default adapter cannot tunnel HTTPS through a TLS proxy. For older axios releases, set proxy: false and pass https-proxy-agent as httpsAgent. Java's built-in HttpClient cannot speak TLS to a proxy at all. If you cannot upgrade, use the SOCKS5 URL.
ETIMEDOUT or ECONNRESET to the partner, or a 403 from the partner
The proxy connected, but the destination dropped you. Usually only one IP of the pair is on the allowlist, or the partner has not applied the change yet. Add both IPs. If a destination allowlist is set on your Fixedmark token, check the host and port are on it.
The IP check prints the platform's IP, not a Fixedmark IP
The request went direct. Node's built-in fetch ignores HTTPS_PROXY unless NODE_USE_ENV_PROXY=1 is set (Node 22.21+ and 24+). Many SDKs ignore proxy env vars too. Pass the proxy to the client explicitly, as in the snippets above.
429 or 407 with an X-Proxy-Error: quota_exceeded header
Planned behavior when you pass your plan's soft limit. Check usage in the dashboard or raise the plan.
Database driver has no proxy option
node-postgres, mysql2, psycopg, and most ORMs cannot use an HTTP proxy. Use a SOCKS5-capable driver with FIXEDMARK_SOCKS_URL, or run bm tunnel where the platform allows a second process.
Gotchas on Vercel
The proxy adds one network hop. Inside the same region it is typically a few milliseconds, but a function in iad1 calling through Mumbai crosses an ocean. Keep regions aligned.
- Edge Middleware and Edge runtime functions cannot use the proxy.
- Next.js data caching does not apply to
fetchimported from undici. That is usually what you want for partner API calls. - Do not set
NODE_USE_ENV_PROXYandHTTPS_PROXYproject-wide. That would send every outbound call through the proxy, including calls that do not need it. - Image Optimization and other Vercel-managed fetches always use Vercel's own IPs.
Related guides
- ComparisonVercel Static IPsVercel's native $100 per project Static IPs compared with a Fixedmark proxy URL shared across projects and platforms.
- Use casePartner API allowlistingGive Salesforce, SOAP vendors, and payment gateways one dedicated IP pair to allowlist, wherever your code runs.
- Use caseMongoDB AtlasReplace 0.0.0.0/0 in your Atlas IP access list with two dedicated IPs, using the Node driver's SOCKS5 support.
- IntegrationSupabase Edge FunctionsFixed outbound IPs for Supabase and Lovable Edge Functions with Deno's proxy client.
- IntegrationNetlifyA fixed source IP for Netlify Functions without an Enterprise contract.
Frequently asked questions
Does Vercel have static IPs?
Yes. Vercel Static IPs is available on Pro and Enterprise plans for $100 per project per month plus Private Data Transfer. Each region gets a static IP pair, up to 3 regions. Hobby projects have no native option.
How do I get a static IP on the Vercel Hobby plan?
Vercel's Static IPs feature is not available on Hobby. Route the calls that need a fixed address through a static IP proxy from a Node.js, Python, or Go function instead.
Can I use one Fixedmark IP pair for several Vercel projects?
Yes. The proxy URL is a credential, not a project setting. Store it in each project's environment variables and all of them leave through the same pair. Use separate tokens per project if you want separate connection logs.
Does this work with Next.js server actions and route handlers?
Yes, on the Node.js runtime. Import fetch and ProxyAgent from undici and pass the agent as the dispatcher option. It does not work on the Edge runtime, because Edge fetch has no proxy setting.
Will my HTTPS traffic be decrypted?
No. Your client opens an HTTP CONNECT tunnel and negotiates TLS with the destination through it. Fixedmark forwards encrypted bytes and logs only connection metadata such as destination host, bytes, and result.
Fix your egress IP.
Fixedmark is in early access. Join the list to get a dedicated IP pair for Vercel when your region opens.