Next.js proxy file reverse proxy
Contents
- If you use a self-hosted proxy, PostHog can't help troubleshoot. Use our managed reverse proxy if you want support.
- Use domains matching your PostHog region:
us.i.posthog.comfor US,eu.i.posthog.comfor EU. - Don't use obvious path names like
/analytics,/tracking,/telemetry, or/posthog. Blockers will catch them. Use something unique to your app instead.
This guide shows you how to use Next.js proxy (formerly middleware) as a reverse proxy for PostHog.
In Next.js 16, middleware.js was renamed to proxy.js. The functionality is identical, but the file and export names changed. If you're on Next.js 15 or earlier, use middleware.js and export middleware instead of proxy.
You can migrate existing middleware using: npx @next/codemod@canary middleware-to-proxy .
How it works
Next.js proxy runs on the edge before a request reaches your pages. When a request matches your proxy path, it rewrites the request to PostHog's servers and returns the response under your domain.
Here's the request flow:
- User triggers an event in your app
- Request goes to your domain (e.g.,
yourdomain.com/ph) - Next.js proxy intercepts the request before it reaches your pages
- Proxy rewrites the request URL to PostHog's servers
- PostHog processes the request and returns a response
- Proxy returns the response to the user under your domain
This works because the proxy runs server-side, so the browser only sees requests to your domain. Ad blockers that filter by domain won't block these requests.
When to use proxy vs rewrites
Next.js offers two ways to proxy PostHog: rewrites and proxy. Both work with the app router and pages router.
- Rewrites: Simpler configuration in
next.config.js. Use this for most cases, especially on Vercel or self-hosted Next.js. - Proxy: More control over request handling. Use this when rewrites return
503or400errors on your hosting platform, or when you need custom logic like header modification.
Try rewrites first. Use proxy if you encounter issues.
Prerequisites
This guide works with any Next.js project using the app router or pages router. Requires Next.js 12.2 or later (use middleware.js for versions before 16, proxy.js for 16+).
Setup
- 1
Create the proxy file
Create a file named
proxy.js(orproxy.tsfor TypeScript) in your project root, at the same level as yourapporpagesfolder:Using Next.js 15 or earlier? Use middleware.js instead
The only differences are the filename (
middleware.js) and the exported function name (middlewareinstead ofproxy).The proxy does the following:
- The
matcherconfig tells Next.js to only run this proxy for requests starting with/ph - It determines which PostHog host to use: the assets host for
/static/*requests, the main host for everything else - It sets the
hostheader so PostHog knows how to route the request. Without this, you'll get 401 errors. - It rewrites the URL to PostHog's domain and strips the
/phprefix
See Next.js proxy documentation for more details.
- The
- 2
Configure trailing slash handling
Add
skipTrailingSlashRedirectto yournext.config.js:JavaScriptPostHog's API endpoints use trailing slashes (like
/e/). Without this setting, Next.js redirects these requests by removing the trailing slash, which breaks event capture. - 3
Update your PostHog SDK
In your application code, update your PostHog initialization to use your proxy path:
The
api_hosttells the SDK where to send events. Using a relative path ensures requests go to your domain. Theui_hostmust point to PostHog's actual domain so features like the toolbar link correctly. - 4
Deploy your changes
Commit and push your changes. The proxy activates once deployed.
In development, restart your dev server after creating the proxy file. Next.js doesn't hot-reload proxy changes.
Verify your setup
CheckpointConfirm events are flowing through your proxy:
- Open your browser's developer tools and go to the Network tab
- Navigate to your site or trigger an event
- Look for requests to your domain with your proxy path (e.g.,
yourdomain.com/ph) - Verify the response status is
200 OK - Check the PostHog app to confirm events appear in your activity feed
If you see errors, check troubleshooting below.
Troubleshooting
Proxy not running
If requests to your proxy path return 404 or don't get proxied:
- Verify your
proxy.js(ormiddleware.jsfor Next.js <16) file is in the project root (same level asapporpages), not inside those folders - Check that the
matcherpattern matches your proxy path - Restart your dev server after creating or modifying the proxy file
Using with Clerk or other auth solutions
If you're using Clerk or similar auth solutions, handle PostHog routes before authentication. Add the proxy logic to your beforeAuth function and exclude the proxy path from auth:
Cookies being forwarded to PostHog
By default, the proxy forwards all headers including cookies to PostHog. If you don't want to forward authentication cookies, delete them from the request:
Alternatively, configure PostHog to use localStorage instead of cookies:
503 or 400 errors persist
If proxy doesn't resolve the errors, your hosting platform may be incompatible with Next.js proxying. Try:
- A platform-specific proxy like Netlify redirects or Vercel rewrites
- PostHog's managed reverse proxy
- Self-hosting Next.js where you control the infrastructure