Headers

    Version History

    Headers allow you to set custom HTTP headers on the response to an incoming request on a given path.

    To set custom HTTP headers you can use the headers key in next.config.js:

    headers is an async function that expects an array to be returned holding objects with source and headers properties:

    • source is the incoming request path pattern.
    • headers is an array of response header objects, with key and value properties.
    • basePath: false or undefined - if false the basePath won’t be included when matching, can be used for external rewrites only.
    • locale: false or undefined - whether the locale should not be included when matching.
    • has is an array of with the type, key and value properties.

    Headers are checked before the filesystem which includes pages and /public files.

    1. module.exports = {
    2. async headers() {
    3. return [
    4. {
    5. source: '/:path*',
    6. headers: [
    7. {
    8. key: 'x-hello',
    9. value: 'there',
    10. },
    11. ],
    12. },
    13. {
    14. source: '/hello',
    15. headers: [
    16. {
    17. key: 'x-hello',
    18. value: 'world',
    19. },
    20. ],
    21. },
    22. ]
    23. },
    24. }

    Path matches are allowed, for example /blog/:slug will match /blog/hello-world (no nested paths):

    1. module.exports = {
    2. async headers() {
    3. return [
    4. {
    5. source: '/blog/:slug',
    6. headers: [
    7. {
    8. key: 'x-slug',
    9. value: ':slug', // Matched parameters can be used in the value
    10. },
    11. {
    12. key: 'x-slug-:slug', // Matched parameters can be used in the key
    13. value: 'my other custom header value',
    14. },
    15. ],
    16. },
    17. ]
    18. }

    To match a wildcard path you can use * after a parameter, for example /blog/:slug* will match /blog/a/b/c/d/hello-world:

    To match a regex path you can wrap the regex in parenthesis after a parameter, for example /blog/:slug(\\d{1,}) will match /blog/123 but not :

    1. module.exports = {
    2. async headers() {
    3. return [
    4. {
    5. source: '/blog/:post(\\d{1,})',
    6. headers: [
    7. {
    8. key: 'x-post',
    9. value: ':post',
    10. },
    11. ],
    12. },
    13. ]
    14. },
    15. }

    The following characters (, ), {, }, :, *, +, ? are used for regex path matching, so when used in the source as non-special values they must be escaped by adding \\ before them:

    1. module.exports = {
    2. async headers() {
    3. return [
    4. {
    5. // this will match `/english(default)/something` being requested
    6. source: '/english\\(default\\)/:slug',
    7. headers: [
    8. {
    9. key: 'x-header',
    10. value: 'value',
    11. },
    12. ],
    13. },
    14. ]
    15. },
    16. }

    To only apply a header when either header, cookie, or query values also match the has field can be used. Both the source and all has items must match for the header to be applied.

    • type: String - must be either header, cookie, host, or query.
    • key: String - the key from the selected type to match against.
    • value: String or undefined - the value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value, e.g. if the value first-(?<paramName>.*) is used for first-second then second will be usable in the destination with :paramName.

    When leveraging basePath support with headers each source is automatically prefixed with the basePath unless you add basePath: false to the header:

    1. module.exports = {
    2. basePath: '/docs',
    3. async headers() {
    4. return [
    5. {
    6. source: '/with-basePath', // becomes /docs/with-basePath
    7. headers: [
    8. {
    9. key: 'x-hello',
    10. value: 'world',
    11. },
    12. ],
    13. {
    14. source: '/without-basePath', // is not modified since basePath: false is set
    15. headers: [
    16. {
    17. key: 'x-hello',
    18. value: 'world',
    19. },
    20. basePath: false,
    21. },
    22. ]
    23. },
    24. }

    When leveraging i18n support with headers each source is automatically prefixed to handle the configured locales unless you add locale: false to the header. If locale: false is used you must prefix the source with a locale for it to be matched correctly.

    1. module.exports = {
    2. i18n: {
    3. locales: ['en', 'fr', 'de'],
    4. defaultLocale: 'en',
    5. },
    6. async headers() {
    7. return [
    8. {
    9. source: '/with-locale', // automatically handles all locales
    10. headers: [
    11. {
    12. key: 'x-hello',
    13. value: 'world',
    14. },
    15. ],
    16. },
    17. {
    18. // does not handle locales automatically since locale: false is set
    19. source: '/nl/with-locale-manual',
    20. locale: false,
    21. headers: [
    22. {
    23. key: 'x-hello',
    24. value: 'world',
    25. },
    26. ],
    27. },
    28. {
    29. // this matches '/' since `en` is the defaultLocale
    30. source: '/en',
    31. locale: false,
    32. headers: [
    33. {
    34. key: 'x-hello',
    35. value: 'world',
    36. },
    37. ],
    38. },
    39. {
    40. // this gets converted to /(en|fr|de)/(.*) so will not match the top-level
    41. // `/` or `/fr` routes like /:path* would
    42. source: '/(.*)',
    43. headers: [
    44. {
    45. key: 'x-hello',
    46. value: 'world',
    47. },
    48. ],
    49. },
    50. ]
    51. }

    You can set the Cache-Control header in your Next.js API Routes by using the res.setHeader method:

    You cannot set Cache-Control headers in next.config.js file as these will be overwritten in production to ensure that API Routes and static assets are cached effectively.

    If you need to revalidate the cache of a page that has been , you can do so by setting the revalidate prop in the page’s getStaticProps function.

    Security HeadersImprove the security of your Next.js application by add HTTP response headers.