Next.js params and searchParams both describe the current URL, but they capture two different parts of it. The params prop holds values from the folder path itself, while the searchParams prop holds values from the query string after the question mark.
/products/running-shoes?sort=price&order=asc
------------- ---------------------
params.slug searchParamsFor a route file at app/products/[slug]/page.tsx, this single URL fills params with the product slug and searchParams with the sort options. Neither prop overlaps with the other.
Where params comes from
A page only receives params when its route has a bracketed folder somewhere in the path. The value comes entirely from the URL's path segments, not from anything after the question mark.
// app/products/[slug]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>{slug}</h1>;
}Visiting /products/running-shoes resolves slug to "running-shoes", regardless of any query string appended to the same URL.
Where searchParams comes from
The searchParams prop holds everything after the question mark, parsed into a plain object. It exists on every page, even one with no dynamic segments in its path at all.
// app/products/[slug]/page.tsx
export default async function Page({
searchParams,
}: {
searchParams: Promise<{ sort?: string }>;
}) {
const { sort } = await searchParams;
return <p>Sort: {sort ?? "default"}</p>;
}Requesting the running shoes page with a sort value of price renders "Sort: price". Leaving off the query string renders "Sort: default" because of the nullish fallback.
Side by side
| params | searchParams | |
|---|---|---|
| Comes from | Folder path segments | Query string after ? |
| Needs a dynamic segment | Yes | No |
| Available in layouts | Yes | No |
| Value type | String or array of strings | Plain object of strings |
Both are request-dependent data, so a layout never receives searchParams even though it can receive params. That rule is covered in more depth in page.js props, params, and search params.
Reading both together
A page can accept both props at once, which is common on a product listing that is both dynamic and filterable.
// app/products/[slug]/page.tsx
type Props = {
params: Promise<{ slug: string }>;
searchParams: Promise<{ sort?: string }>;
};
export default async function Page({ params, searchParams }: Props) {
const { slug } = await params;
const { sort } = await searchParams;
return <p>{slug} sorted by {sort ?? "default"}</p>;
}Awaiting each prop separately keeps the two sources of data clearly labeled in the code, which matters once a page reads several dynamic segments alongside several query values. For the fully worked-out dynamic segment example on its own, see dynamic routes in Next.js.
Common mistake
Mixing up the two names is the most common mistake, especially when a route has both a dynamic segment and query filters. If a value is missing where you expect it, check whether it actually lives in the path or in the query string, since reading the wrong prop returns undefined instead of an error.
A second mistake is reaching for params when the value should really change without a page reload, such as a sort order a visitor toggles repeatedly. Because params comes from the folder structure, changing it means navigating to a different URL entirely, while a searchParams value can update in place through a link or a router call. Choosing the wrong one early tends to force a larger rewrite later, so decide up front whether a value identifies a resource or merely adjusts how it is displayed.
Rune AI
Key Insights
- params comes from dynamic segments defined by folder names in the route.
- searchParams comes from the query string that follows the question mark in a URL.
- Both are promises on the page prop and must be awaited or unwrapped with use.
- Only pages receive searchParams; layouts only receive params.
- The useSearchParams hook is the Client Component alternative to the page prop.
Frequently Asked Questions
Can a page use params and searchParams at the same time?
Why does reading searchParams make a page dynamic?
Is searchParams a URLSearchParams instance?
Conclusion
params captures values from the folder structure of the path, and searchParams captures the query string after the question mark. Reach for params to identify a resource and searchParams to filter, sort, or paginate it.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.