Skip to main content
The redirect function lets you redirect the user to another URL. It can be used in Server Components, Route Handlers, and Server Functions.

redirect()

import { redirect } from 'next/navigation'

redirect(path, type?)
Issues a 307 Temporary Redirect (or a meta redirect when used inside a streaming context). In Server Actions it issues a 303 See Other.

Parameters

path
string
required
The URL to redirect to. Can be a relative or absolute path.
type
'replace' | 'push'
The redirect type. Defaults to 'push' in Server Actions and 'replace' everywhere else.
You can use the RedirectType enum for the type parameter:
import { redirect, RedirectType } from 'next/navigation'

redirect('/new-page', RedirectType.replace)
redirect('/new-page', RedirectType.push)
The type parameter has no effect in Server Components.

Returns

redirect does not return a value. It throws a NEXT_REDIRECT error internally, so it does not need return redirect(...) — the TypeScript type is never.

permanentRedirect()

import { permanentRedirect } from 'next/navigation'

permanentRedirect(path, type?)
Identical to redirect but issues a 308 Permanent Redirect instead of 307.

Behavior

  • In Server Actions and Route Handlers, call redirect outside any try/catch block, since it works by throwing an error.
  • redirect can be called in Client Components during rendering, but not inside event handlers. Use useRouter for event-driven navigation.
  • redirect accepts absolute URLs for external redirects.
  • To redirect before rendering, use redirects in next.config.js.

Why 307 and 308?

Traditional 302 and 301 redirects caused browsers to downgrade POST requests to GET. Using 307 (temporary) and 308 (permanent) preserves the original HTTP method.

Examples

Server Component

app/team/[id]/page.tsx
import { redirect } from 'next/navigation'

async function fetchTeam(id: string) {
  const res = await fetch(`https://api.example.com/teams/${id}`)
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const team = await fetchTeam(id)

  if (!team) {
    redirect('/login')
  }

  return <div>{team.name}</div>
}

Client Component (during render)

components/client-redirect.tsx
'use client'

import { redirect, usePathname } from 'next/navigation'

export function ClientRedirect() {
  const pathname = usePathname()

  if (pathname.startsWith('/admin') && !pathname.includes('/login')) {
    redirect('/admin/login')
  }

  return <div>Admin area</div>
}
When used in a Client Component during initial SSR, this performs a server-side redirect.

Via a Server Action

app/actions.ts
'use server'

import { redirect } from 'next/navigation'

export async function navigate(data: FormData) {
  redirect(`/posts/${data.get('id')}`)
}
app/client-form.tsx
'use client'

import { navigate } from './actions'

export function ClientForm() {
  return (
    <form action={navigate}>
      <input type="text" name="id" />
      <button>Go to post</button>
    </form>
  )
}

Version history

VersionChanges
v13.0.0redirect introduced.

Build docs developers (and LLMs) love