Rewrites

Rewrites on Vercel

Last updated January 23, 2026

A rewrite routes a request to a different destination without changing the URL in the browser. Unlike redirects, the user won't see the URL change.

There are two main types:

  1. Same-application rewrites – Route requests to different pages within your Vercel project.
  2. External rewrites – Forward requests to an external API or website.

The /.well-known path is reserved and cannot be redirected or rewritten. Only Enterprise teams can configure custom SSL. Contact sales to learn more.

Rewrites are defined in a vercel.json file in your project's root directory:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/source-path",
      "destination": "/destination-path"
    }
  ]
}

For all configuration options, see the project configuration docs.

Same-application rewrites route requests to different destinations within your project. Common uses include:

  • Friendly URLs: Transform /products/t-shirts into /catalog?category=t-shirts
  • Device-specific content: Show different layouts based on device type
  • A/B testing: Route users to different versions of a page
  • Country-specific content: Show region-specific content based on the user's location

Example: Route image resize requests to a serverless function:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/resize/:width/:height",
      "destination": "/api/sharp"
    }
  ]
}

This converts a request like /resize/800/600 to /api/sharp?width=800&height=600.

Example: Route UK visitors to a UK-specific section:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/:path((?!uk/).*)",
      "has": [
        { "type": "header", "key": "x-vercel-ip-country", "value": "GB" }
      ],
      "destination": "/uk/:path*"
    }
  ]
}

This routes a UK visitor requesting /about to /uk/about.

External rewrites forward requests to APIs or websites outside your Vercel project, effectively allowing Vercel to function as a reverse proxy or standalone CDN. You can use this feature to:

  • Proxy API requests: Hide your actual API endpoint
  • Combine multiple services: Merge multiple backends under one domain
  • Create microfrontends: Combine multiple Vercel applications into a single website
  • Add caching: Cache external API responses on the CDN
  • Serve externally hosted content: Serve content that is not hosted on Vercel.

Example: Forward API requests to an external endpoint:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/api/:path*",
      "destination": "https://api.example.com/:path*"
    }
  ]
}

A request to /api/users will be forwarded to https://api.example.com/users without changing the URL in the browser.

External rewrites aren't cached by default. To enable caching, add the x-vercel-enable-rewrite-caching header to your vercel.json:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/api/:path*",
      "destination": "https://api.example.com/:path*"
    }
  ],
  "headers": [
    {
      "source": "/api/:path*",
      "headers": [{ "key": "x-vercel-enable-rewrite-caching", "value": "1" }]
    }
  ]
}

This tells Vercel to respect caching headers on the upstream response. Once enabled, you can control the cache duration in two ways:

  1. From your API (preferred): When you control the backend, return CDN-Cache-Control or Vercel-CDN-Cache-Control headers in the API response:

    CDN-Cache-Control: max-age=60

    This caches the response on the CDN for 60 seconds.

  2. From Vercel configuration: When you can't modify the backend, set caching headers in vercel.json alongside x-vercel-enable-rewrite-caching:

    vercel.json
    {
      "$schema": "https://openapi.vercel.sh/vercel.json",
      "rewrites": [
        {
          "source": "/api/:path*",
          "destination": "https://api.example.com/:path*"
        }
      ],
      "headers": [
        {
          "source": "/api/:path*",
          "headers": [
            { "key": "x-vercel-enable-rewrite-caching", "value": "1" },
            {
              "key": "CDN-Cache-Control",
              "value": "max-age=60"
            }
          ]
        }
      ]
    }

    This caches the response on the CDN for 60 seconds.

For more information on caching headers, see the Cache-Control headers documentation.

When caching external rewrites, it's best practice to also include a Vercel-Cache-Tag response header with a comma-separated list of tags so you can later purge the CDN cache by tag at your convenience.

You can export external rewrite data by draining logs from your application. External rewrite events appear in your runtime logs, allowing you to monitor proxy requests, track external API calls, and analyze traffic patterns to your backend services.

To get started, configure a logs drain.

You can observe your external rewrite performance using Observability. The External Rewrites tab shows request counts, connection latency, and traffic patterns for your proxied requests, helping you monitor backend performance and validate that rewrites are working as expected.

Learn more in the Observability Insights documentation.

External rewrites work universally with all frameworks, making them ideal for API proxying, microfrontend architectures, and serving content from external origins through Vercel's global network as a reverse proxy or standalone CDN.

For same-application rewrites, always prefer your framework's native routing capabilities:

Use vercel.json rewrites for same-application routing only when your framework doesn't provide native routing features. Always consult your framework's documentation for the recommended approach.

Use Vercel's preview deployments to test your rewrites before going to production. Each pull request creates a unique preview URL where you can verify your rewrites work correctly.

You can capture and forward parts of a path using wildcards:

{
  "rewrites": [
    {
      "source": "/docs/:path*",
      "destination": "/help/:path*"
    }
  ]
}
Some redirects and rewrites configurations can accidentally become gateways for semantic attacks. Learn how to check and protect your configurations with the Enhancing Security for Redirects and Rewrites guide.

A request to /docs/getting-started/install will be forwarded to /help/getting-started/install.

You can also capture multiple path segments:

{
  "rewrites": [
    {
      "source": "/blog/:year/:month/:slug*",
      "destination": "/posts?date=:year-:month&slug=:slug*"
    }
  ]
}

For more complex patterns, you can use regular expressions with capture groups:

{
  "rewrites": [
    {
      "source": "^/articles/(\\d{4})/(\\d{2})/(.+)$",
      "destination": "/archive?year=$1&month=$2&slug=$3"
    }
  ]
}

This converts /articles/2023/05/hello-world to /archive?year=2023&month=05&slug=hello-world.

You can also use named capture groups:

{
  "rewrites": [
    {
      "source": "^/products/(?<category>[a-z]+)/(?<id>\\d+)$",
      "destination": "/shop?category=$category&item=$id"
    }
  ]
}

This converts /products/shirts/123 to /shop?category=shirts&item=123.

  • Same-application rewrites: Use when routing within your own application
  • External rewrites: Use when connecting to external APIs, creating microfrontends, or using Vercel as a reverse proxy or standalone CDN for third-party content

Was this helpful?

supported.