# Proxying the Clerk Frontend API

> This feature or workflow is considered **advanced** - it may not be part of an official Clerk SDK or fall within typical usage patterns. The Clerk support team will do their best to assist you, but cannot guarantee a resolution for this type of advanced usage.

Clerk supports two configuration methods for connecting to the Clerk Frontend API: CNAME and Proxy.

The recommended way to connect to the Clerk Frontend API is to [set up CNAME records and use DNS](https://clerk.com/docs/guides/development/deployment/production.md). However, if you're unable to use this approach, or would like more control over your integration with Clerk, you can use a proxy.

When using a proxy, all requests to the Frontend API will be made through your domain. This allows you to use your own SSL certificate, and gives you more control over how you configure your application.

> This guide is for users who need to proxy the Frontend API for **production** (proxying does not work for Clerk development instances). If your application already uses a CNAME subdomain that is required for deploying with Clerk, then you must proxy the Frontend API using a different subdomain. Refer to the [deployment guide](https://clerk.com/docs/guides/development/deployment/production.md#dns-records) on how to configure DNS records for deployment.

## How to use proxying

1. ### Create your application and install Clerk

   To get started, you need to create an application from the [Clerk Dashboard](https://dashboard.clerk.com/). Once you create an instance via the Clerk Dashboard, you will be prompted to choose a domain. For the purposes of this guide, the domain will be `app.dev`.

   > For more information on creating a Clerk application, see the [setup guide](https://clerk.com/docs/getting-started/quickstart/setup-clerk.md).
2. ### Configure your proxy server

   For this example, `/__clerk` is used as the path for the proxy. Your proxy server must be on the same domain as your application.

   You can choose any path you'd like, but it must be unique and not conflict with any other routes in your application.
3. #### Requirements

   Requests to `https://app.dev/__clerk/*` must be forwarded to `https://frontend-api.clerk.dev/*` with the body and all headers intact.

   Three additional headers must be set

   - `Clerk-Proxy-Url`: Needs to have the full proxy URL.
   - `Clerk-Secret-Key`: Your Clerk Secret Key.
   - `X-Forwarded-For`: The IP address of the original client making the request.
4. #### Example configuration

   **Next.js**

   If you're using **Next.js**, you can configure a frontend API proxy in one of two ways:

   - Use the built-in `frontendApiProxy` option in [clerkMiddleware()](https://clerk.com/docs/reference/nextjs/clerk-middleware.md#frontend-api-proxy).
   - Use [createFrontendApiProxyHandlers()](https://clerk.com/docs/reference/nextjs/clerk-middleware.md#create-frontend-api-proxy-handlers) in a Next.js App Router route handler. **This is useful if you prefer to keep proxy logic separate from your middleware.**

   **Using clerkMiddleware()**

   The `frontendApiProxy` option in `clerkMiddleware()` handles all proxy requirements automatically, including header forwarding, body streaming, and redirect rewriting. The `proxyUrl` for authentication handshake is also auto-derived.

   > Ensure your middleware matcher includes the proxy path (by default, `/__clerk`) so proxy requests are handled by the middleware.

   filename: proxy.ts

   ```ts
   import { clerkMiddleware } from '@clerk/nextjs/server'

   export default clerkMiddleware({
     frontendApiProxy: {
       enabled: true,
     },
   })

   export const config = {
     matcher: [
       // Skip Next.js internals and all static files, unless found in search params
       '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
       // Always run for API routes
       '/(api|trpc)(.*)',
       // Always run for Clerk-specific frontend API routes
       '/__clerk/(.*)',
     ],
   }
   ```

   For applications that serve multiple domains (e.g., preview deployments, staging environments), you can pass a function to `enabled` to conditionally enable proxying based on the request URL.

   filename: proxy.ts

   ```ts
   import { clerkMiddleware } from '@clerk/nextjs/server'

   export default clerkMiddleware({
     frontendApiProxy: {
       // Only proxy on non-production domains
       enabled: (url) => url.hostname !== 'myapp.com',
     },
   })

   export const config = {
     matcher: [
       // Skip Next.js internals and all static files, unless found in search params
       '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
       // Always run for API routes
       '/(api|trpc)(.*)',
       // Always run for Clerk-specific frontend API routes
       '/__clerk/(.*)',
     ],
   }
   ```

   **Using createFrontendApiProxyHandlers()**

   As an alternative to the middleware approach, you can use `createFrontendApiProxyHandlers()` in a Next.js App Router route handler.

   > When using route handlers instead of the `frontendApiProxy` middleware option, the `proxyUrl` is **not** auto-derived. You must set the `proxyUrl` option on `clerkMiddleware()` or set the `NEXT_PUBLIC_CLERK_PROXY_URL` environment variable for the authentication handshake to work correctly.

   > In Next.js App Router, folders that start with `_` are treated as [private folders](https://nextjs.org/docs/app/getting-started/project-structure#private-folders). To create a literal `__clerk` route segment, use `%5F%5Fclerk` in the file path. The resulting route is still `/__clerk/*`.

   filename: app/api/%5F%5Fclerk/[[...path]]/route.ts

   ```ts
   import { createFrontendApiProxyHandlers } from '@clerk/nextjs/server'

   export const { GET, POST, PUT, DELETE, PATCH } = createFrontendApiProxyHandlers()
   ```

   > Every proxy configuration will be different. [Contact support](https://clerk.com/contact/support){{ target: '_blank' }} if you need help with a specific use case.
5. ### Enable proxying

   In order to enable proxying, you need to set a proxy URL for your Clerk instance's domain. This can be done through the Clerk Dashboard or through the Backend API.

   > To avoid downtime, your proxy must be set up according to the above configuration before it can be enabled for your instance.
   > Make sure your proxy forwards requests to the Clerk Frontend API correctly and includes the required headers.

   **Dashboard**

   1. In the Clerk Dashboard, navigate to the **[Domains](https://dashboard.clerk.com/~/domains)** page.
   2. In the **Frontend API** section, select the **Set proxy configuration** option.
   3. Enter your proxy URL. The proxy URL must be a valid URL and resolve correctly.

   **Backend API**

   The request below will update the domain to use the proxy URL `https://app.dev/__clerk`. In doing so, it will trigger checks to validate the proxy URL.

   ```bash
   curl -X PATCH https://api.clerk.com/v1/domains/{{DOMAIN ID}} \
       -H "Authorization: Bearer {{SECRET KEY}}" \
       -H "Content-Type: application/json" \
       -d '{"proxy_url": "https://app.dev/__clerk"}'
   ```
6. ### Configure your proxy setup

   > If you used the `frontendApiProxy` option in `clerkMiddleware()` (Next.js or Express), the server-side `proxyUrl` is auto-derived from the proxy configuration. You only need to set the client-side environment variable (e.g., `NEXT_PUBLIC_CLERK_PROXY_URL`) so that ClerkJS in the browser routes requests through the proxy.

   You can configure your proxy setup by either:

   - Setting environment variables
   - Using properties in your application
7. #### Environment variables

   To configure your proxy setup using environment variables, your `.env` file should look like this:

   **Next.js**

   filename: .env

   ```env
   NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}}
   CLERK_SECRET_KEY={{secret}}

   NEXT_PUBLIC_CLERK_PROXY_URL=https://app.dev/__clerk/
   ```
8. #### Properties in your application

   **Next.js**

   To configure your proxy setup using properties in your Next.js application, set the `proxyUrl` property on the [<ClerkProvider>](https://clerk.com/docs/reference/components/clerk-provider.md) component.

   filename: app/layout.tsx

   ```tsx
   import { ClerkProvider } from '@clerk/nextjs'

   export default function RootLayout({ children }: { children: React.ReactNode }) {
     return (
       <html lang="en">
         <body>
           <ClerkProvider proxyUrl="https://app.dev/__clerk/">{children}</ClerkProvider>
         </body>
       </html>
     )
   }
   ```
9. ### Ready to go 🎉

   Your application should now be able to access the Frontend API from your proxy!

## Proxying for satellite domains

If you use [satellite domains](https://clerk.com/docs/guides/dashboard/dns-domains/satellite-domains.md) and are unable to add a CNAME record for the Clerk Frontend API, you can proxy it instead. This replaces the CNAME-based DNS setup described in the satellite domains guide.

You can mostly follow the same steps as for adding a proxy to your primary domain detailed above, but for your satellite domain instead.

1. ### Add your satellite domain

   Start by adding your satellite domain to the Clerk Dashboard and configure `allowedRedirectOrigins` on your primary domain app. See the [satellite domains guide](https://clerk.com/docs/guides/dashboard/dns-domains/satellite-domains.md#add-your-first-satellite-domain) for instructions.
2. ### Configure your proxy server

   Set up a proxy on your satellite domain that forwards requests to Clerk's Frontend API. The requirements are the same as [configuring a proxy for a primary domain](#configure-your-proxy-server) — requests to your satellite's proxy path (e.g., `https://satellite.dev/__clerk/*`) must be forwarded to `https://frontend-api.clerk.dev/*` with the body, all headers, and the three required additional headers (`Clerk-Proxy-Url`, `Clerk-Secret-Key`, `X-Forwarded-For`).
3. ### Enable proxying for the satellite domain

   **Dashboard**

   1. In the Clerk Dashboard, navigate to the **[Domains](https://dashboard.clerk.com/~/domains)** page.
   2. Select the **Satellites** tab.
   3. Select your satellite domain.
   4. Set the proxy URL (e.g., `https://satellite.dev/__clerk`). The proxy URL must be a valid URL and resolve correctly.

   **Backend API**

   The request below will update the satellite domain to use a proxy URL. Replace `{{DOMAIN ID}}` with your satellite domain's ID.

   ```bash
   curl -X PATCH https://api.clerk.com/v1/domains/{{DOMAIN ID}} \
       -H "Authorization: Bearer {{SECRET KEY}}" \
       -H "Content-Type: application/json" \
       -d '{"proxy_url": "https://satellite.dev/__clerk"}'
   ```
4. ### Configure your satellite app

   You can now configure your satellite app to use the proxy, either via environment variables or by using properties in your application. See the [Configure your proxy setup](#configure-your-proxy-setup) section for more information.

   > When using a proxy for a satellite domain, you set `proxyUrl` / `CLERK_PROXY_URL` **instead of** `domain` / `CLERK_DOMAIN`. The `proxyUrl` replaces `domain` — you should not set both.
5. ### Ready to go 🎉

   Your satellite application should now be able to access the Frontend API from your proxy!

If you have any questions about proxying, or you're having any trouble setting this up, contact [support@clerk.com](mailto:support@clerk.com).

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
