Most developers treat pagination as a minor routing concern—slap on query parameters, call it done. But pagination is one of the most mishandled areas of technical SEO, and getting it wrong means pages 2 through 50 stay invisible to search engines. This guide covers pagination and SEO: a technical SEO guide for developers, with the concrete patterns you need to make every page in a series discoverable, crawlable, and rankable.
Why pagination matters for SEO
When you have product listings, blog archives, or search results that span dozens of pages, each page represents an opportunity for organic traffic. But search engines don't automatically discover or value page 2 the same way they value page 1. Without proper structure, Google crawls your paginated content inefficiently, ranks it poorly, or misses it entirely.
The stakes are real: an e-commerce site with 50 pages of product results can lose millions in impressions if those pages aren't indexable. A SaaS documentation site with paginated API reference lists won't surface the specific endpoint a developer searches for if it's buried on page 7 with no clear path.
Pagination affects crawl budget, indexation, ranking signals, and user experience. Get it right, and secondary pages earn their own search traffic. Get it wrong, and they dilute your primary page's authority.
Unique URLs per page — each crawlable and linkable
The foundation of paginated SEO is this: every page in a series must have its own unique, permanent URL. This is non-negotiable.
Choose one of these patterns and stick to it:
- Query parameter:
example.com/products?page=2 - Path segment:
example.com/products/page/2 - Offset:
example.com/products?offset=20&limit=20
Query parameters are most common and work fine. Path segments feel cleaner and are equally valid. What matters is consistency and stability—don't change your pagination scheme mid-stream, as old URLs will 404 and you'll lose all accumulated ranking signals.
Each URL should return a unique set of content. If /products?page=2 and /products?page=1 return the same items, you've created duplicate content. Pagination exists to chunk large datasets; use it to actually paginate.
Here's a simple Node.js + Express example:
app.get('/products', (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const offset = (page - 1) * limit;
const products = getProducts(offset, limit);
const totalCount = getTotalProductCount();
const totalPages = Math.ceil(totalCount / limit);
res.render('products', {
products,
page,
totalPages,
hasNext: page < totalPages,
hasPrev: page > 1
});
});This controller ensures each ?page=N URL fetches and renders distinct products. The URL is crawlable and linkable—a search bot can discover it, follow it, and index its content.
Real links — use anchor tags, not buttons with JavaScript handlers
Search engine crawlers follow HTML links. They do not reliably execute JavaScript, click buttons, or trigger fetch requests to load new pages dynamically. If your pagination uses JavaScript event handlers instead of real anchor tags, pages 2 onward become invisible to SEO.
This is wrong:
<button onclick="goToPage(2)">Next</button>
<button @click="page = page + 1">Next</button>Google's crawler may execute some JavaScript, but it's unreliable for pagination. A crawler might miss the page entirely, fail to index it, or assign it lower priority. In production systems handling millions of pages, you cannot risk this uncertainty.
This is correct:
<a href="/products?page=2">Next</a>
<a href="/products?page=1">Previous</a>
<a href="/products?page=5">5</a>Real anchor tags with href attributes are crawlable, linkable, and work for users without JavaScript. If you use a framework like Next.js or React Router, ensure your pagination links render as real <a> tags in the final HTML:
// Next.js example
<Link href={`/products?page=${page + 1}`}>
<a>Next</a>
</Link>
// React with standard routing
<a href={`/products?page=${page + 1}`}>Next</a>When server-side rendered or statically generated, these produce real HTML links that crawlers follow immediately. If you're building a purely client-side app, you must either pre-render pagination links at build time or use dynamic rendering to ensure crawlers see the links.
Self-canonical pages — page 2 canonicalizes to itself
A common mistake is to add a canonical tag pointing all paginated pages back to page 1. This tells search engines: "This page 2 is not unique; treat it as duplicate of page 1." Google then ignores page 2 for indexation and ranking. That's the opposite of what you want.
This is wrong:
<!-- On /products?page=2 -->
<link rel="canonical" href="/products" />This is correct:
<!-- On /products?page=1 -->
<link rel="canonical" href="/products?page=1" />
<!-- On /products?page=2 -->
<link rel="canonical" href="/products?page=2" />
<!-- On /products?page=3 -->
<link rel="canonical" href="/products?page=3" />Each page should canonicalize to itself. This signals to Google: "This is a unique, standalone page. Index and rank it." If you have parameter variations (sorting, filtering), then canonical tags become more complex, but for straightforward pagination, self-canonicalization is the rule.
In practice, this often means setting the canonical dynamically based on the current request URL:
// Express middleware to set canonical
app.use((req, res, next) => {
const protocol = req.protocol;
const host = req.get('host');
const path = req.originalUrl;
res.locals.canonical = `${protocol}://${host}${path}`;
next();
});
// In your template
<link rel="canonical" href="<%= canonical %>" />This ensures every page, regardless of position in the sequence, points to its own URL as the canonical version.
rel=prev/next is retired — strong internal linking matters more
Google officially stopped using rel=prev and rel=next tags for ranking and crawl prioritization in 2019. Many developers still add them, thinking it helps. It doesn't hurt, but it's also not necessary.
Before 2019, these tags helped Google understand pagination relationships:
<!-- On /products?page=2 -->
<link rel="prev" href="/products?page=1" />
<link rel="next" href="/products?page=3" />Google now discovers and crawls paginated sequences through real anchor links. If page 1 links to page 2, page 2 links to page 3, and so on, Google understands the series automatically. The crawler follows the chain, indexes each page, and assigns ranking potential to later pages based on overall site authority and the quality of content on that page.
What matters instead:
- Strong, visible internal links: Make pagination controls prominent and crawlable. Don't hide them behind collapsed menus or lazy-loaded sections.
- Logical link flow: Link sequentially (page 1 → page 2 → page 3) and also provide skip links or a page picker so crawlers can reach page 10 without traversing every intermediate page.
- Context and anchors: Use descriptive anchor text. "Next page" is fine; "Click here" wastes a signal.
If your pagination includes a "Jump to page" picker, make sure each option is a real link:
<div class="pagination">
<a href="/products?page=1">1</a>
<a href="/products?page=2">2</a>
<a href="/products?page=3">3</a>
<!-- ... -->
<a href="/products?page=10">10</a>
<a href="/products?page=<%= currentPage + 1 %>">Next</a>
</div>This lets crawlers hop directly to distant pages instead of crawling sequentially through every intermediate page, saving crawl budget.
Common mistakes
- Canonicalizing paginated pages to page 1: This deindexes secondary pages. Each page must canonical to itself.
- Using JavaScript-only pagination: If links are generated by client-side JavaScript without pre-rendering or dynamic rendering, crawlers won't discover page 2 through page 50. Use real HTML links.
- Inconsistent pagination schemes: Changing from
?page=2to/page/2/mid-stream causes 404s and lost ranking signals. Pick one scheme and maintain it. - Duplicate content across pages: If every page shows the same 5 items, pagination serves no purpose and wastes crawl budget. Ensure each page displays distinct content.
- No internal links to secondary pages: If page 1 is your only entry point and secondary pages have no other internal links, they're orphaned. Link to them from your main site navigation or category pages.
- Blocking pagination in robots.txt: Some teams accidentally block
?page=*or/page/*patterns. Verify your robots.txt doesn't exclude paginated URLs. - Relying on rel=prev/next: It's not harmful to include, but don't assume it compensates for missing anchor links or poor crawlability.
Key takeaways
- Every paginated page needs a unique, permanent URL that's crawlable and linkable.
- Use real HTML anchor tags for pagination controls; avoid JavaScript-only navigation.
- Set each page's canonical tag to point to itself, not to page 1.
- Rely on real internal links for discoverability, not rel=prev/next.
- Make pagination prominent and provide skip links so crawlers can reach distant pages without traversing the entire sequence.
- Keep pagination schemes consistent over time to preserve accumulated ranking signals.
- Ensure each paginated page displays genuinely distinct content; don't create duplicate pages.






Comments
Loading comments…