← Blog

How to Proxy Claude API Requests: A Practical Guide

2026-10-04 · 5 min read · SubToAPI Team

Proxying Claude API requests means routing calls through your own server (or a managed service) instead of hitting Anthropic's endpoint directly from client code. You do this to hide your real API key from end users, add logging or rate limiting, normalize responses for your app, or issue separate keys to different teams and products without sharing one master credential.

The short answer: you build a thin HTTP server that accepts requests from your app, forwards them to Anthropic with your actual credentials, and streams the response back. Below is exactly how to do that, what breaks when you try it at scale, and when it's faster to use a managed proxy instead of maintaining your own.

Why proxy Claude API calls at all

Calling the Claude API directly from a browser or mobile app is a non-starter — your key would be exposed in the request headers of every client. Even in server-to-server setups, teams end up building a proxy layer for a few recurring reasons:

If you only need one or two of these, a few lines of middleware might be enough. If you need all of them reliably, you're building (or buying) a real API gateway.

Building a minimal Claude API proxy

Here's a bare-bones Node.js/Express proxy that forwards requests to Anthropic, adds a simple API key check, and logs token usage:

import express from "express";
import fetch from "node-fetch";

const app = express();
app.use(express.json());

const INTERNAL_KEYS = new Set(["app-1-key", "app-2-key"]);

app.post("/v1/messages", async (req, res) => {
  const incomingKey = req.headers["x-internal-key"];
  if (!INTERNAL_KEYS.has(incomingKey)) {
    return res.status(401).json({ error: "invalid key" });
  }

  const upstream = await fetch("https://api.anthropic.com/v1/messages", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-api-key": process.env.ANTHROPIC_API_KEY,
      "anthropic-version": "2023-06-01",
    },
    body: JSON.stringify(req.body),
  });

  const data = await upstream.json();
  console.log("usage:", data.usage, "caller:", incomingKey);
  res.status(upstream.status).json(data);
});

app.listen(3000);

This works for basic, non-streaming calls. The moment you need more, the complexity grows fast:

None of this is hard in isolation. It's the combination, maintained over time, that turns a "quick proxy" into an on-call liability.

Streaming through a proxy correctly

If you're forwarding streaming responses, don't buffer the body before sending it to the client — pipe it directly:

app.post("/v1/messages", async (req, res) => {
  const upstream = await fetch("https://api.anthropic.com/v1/messages", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-api-key": process.env.ANTHROPIC_API_KEY,
      "anthropic-version": "2023-06-01",
    },
    body: JSON.stringify({ ...req.body, stream: true }),
  });

  res.setHeader("Content-Type", "text/event-stream");
  upstream.body.pipe(res);
});

This is the minimum. A production proxy also needs to handle partial chunks that split across TCP packets, client aborts mid-stream, and timeouts that don't leave open connections hanging on the upstream side.

Using a managed proxy instead

If the goal is just "give my app a Claude endpoint I control, with keys, logs, and usage data," building and maintaining this yourself is often more work than the feature is worth. SubToAPI is built specifically for this: it sits between your Claude access and your applications, issuing scoped sub_live_... keys per app or team, handling streaming and tool use correctly, and giving you usage metadata without you writing a proxy server at all.

In practice that means:

A minimal call looks like this:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 512,
    "messages": [{"role": "user", "content": "Summarize this proxy setup."}]
  }'

Plans start at €9/month for solo use, with per-seat pricing for teams on /pricing, and a free trial at /signup if you want to compare it against a hand-rolled proxy before committing. The quickstart at /docs/quickstart covers the full setup in a few minutes.

Which approach to pick

Build your own proxy if you need very specific request transformations, have an existing gateway infrastructure you must integrate with, or you're only forwarding a handful of simple, non-streaming calls. Reach for a managed layer like SubToAPI if you want per-app keys, streaming, tool use, and usage tracking without owning the operational burden of running and patching that server yourself.

FAQ

Is proxying the Claude API against Anthropic's terms?

No — proxying is a normal architectural pattern for hiding credentials and adding infrastructure like logging or rate limiting. What matters is that your usage still complies with Anthropic's acceptable use policies regardless of how requests are routed.

Does a proxy add latency to Claude API calls?

Yes, a small amount — typically single-digit to low double-digit milliseconds for the extra network hop, assuming your proxy is reasonably close to Anthropic's infrastructure and isn't doing heavy synchronous processing per request.

Can a proxy handle streaming and tool use, not just plain text?

Yes, but it has to be built for it specifically — piping SSE chunks without buffering and correctly round-tripping tool_use/tool_result blocks. A basic request-response proxy will break both unless it's designed with these in mind from the start.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →