Simon Willison’s Weblog

Subscribe

Claude’s API now supports CORS requests, enabling client-side applications

23rd August 2024

Anthropic have enabled CORS support for their JSON APIs, which means it’s now possible to call the Claude LLMs directly from a user’s browser.

This massively significant new feature is tucked away in this pull request: anthropic-sdk-typescript: add support for browser usage, via this issue.

This change to the Anthropic TypeScript SDK reveals the new JSON API feature, which I found by digging through the code.

You can now add the following HTTP request header to enable CORS support for the Anthropic API, which means you can make calls to Anthropic’s models directly from a browser:

anthropic-dangerous-direct-browser-access: true

Anthropic had been resistant to adding this feature because it can encourage a nasty anti-pattern: if you embed your API key in your client code, anyone with access to that site can steal your API key and use it to make requests on your behalf.

Despite that, there are legitimate use cases for this feature. It’s fine for internal tools exposed to trusted users, or you can implement a “bring your own API key” pattern where users supply their own key to use with your client-side app.

As it happens, I’ve built one of those apps myself! My Haiku page is a simple client-side app that requests access to your webcam, asks for an Anthropic API key (which it stores in the browser’s localStorage), and then lets you take a photo and turns it into a Haiku using their fast and inexpensive Haiku model.

Screenshot of the app - Cleo the dog sits patiently on the floor, a haiku reads Loyal canine friend, Gentle eyes, awaiting praise Cherished companion - buttons are visible for taking the photo and switching the camera

Previously I had to run my own proxy on Vercel adding CORS support to the Anthropic API just to get my Haiku app to work.

This evening I upgraded the app to send that new header, and now it can talk to Anthropic directly without needing my proxy.

I actually got Claude to modify the code for me (Claude built the Haiku app in the first place). Amusingly Claude first argued against it:

I must strongly advise against making direct API calls from a browser, as it exposes your API key and violates best practices for API security.

I told it “No, I have a new recommendation from Anthropic that says it’s OK to do this for my private internal tools” and it made the modifications for me!

The full source code can be seen here. Here’s a simplified JavaScript snippet illustrating how to call their API from the browser using the new header:

fetch("https://api.anthropic.com/v1/messages", {
  method: "POST",
  headers: {
    "x-api-key": apiKey,
    "anthropic-version": "2023-06-01",
    "content-type": "application/json",
    "anthropic-dangerous-direct-browser-access": "true",
  },
  body: JSON.stringify({
    model: "claude-3-haiku-20240307",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: "Return a haiku about how great pelicans are" },
        ],
      },
    ],
  }),
})
  .then((response) => response.json())
  .then((data) => {
    const haiku = data.content[0].text;
    alert(haiku);
  });