/ โ† Site Crawler Fixes / Pagination SEO
In this guide
  1. What pagination is and how it works
  2. Pagination problems that hide pages from search
  3. How to add pagination in HTML
  4. Implementing it on the server, and does pagination improve performance?
  5. Pagination in WordPress, Shopify and Next.js
  6. A worked example: a recipe archive
  7. The fix, step by step
  8. Edge cases worth knowing
  9. Keeping pagination crawlable
  10. Questions and answers

What pagination is and how it works

Pagination means dividing a set of items into pages of a fixed size and giving the visitor controls to move between them: previous, next and numbered page links. In web development, each page is normally a separate request. The server works out which slice of items to show from a page number in the address, such as /blog/page/3/ or /shoes?page=3, and returns just those items with links to the other pages.

The arithmetic is simple. With 24 items per page, page 3 shows items 49 to 72:

per_page = 24
offset   = (page - 1) * per_page      # page 3 -> skip 48 items
pages    = ceil(total_items / per_page)  # 500 items -> 21 pages

For search engines, each page in the series is just another URL. Google crawls page 1, follows the link to page 2, and so on, discovering the posts or products linked from each one. That is why pagination is a crawling question, not only a design one: an item that is only linked from page 14 is found only if the crawler can reach page 14.

๐Ÿ’ก Google stopped using rel="next" and rel="prev" as an indexing signal some years ago. They do no harm and other systems may read them, but they do not replace normal links between the pages.

Pagination problems that hide pages from search

ProblemWhat happensThe fix
Page links are buttons or JavaScript onlyCrawlers cannot follow them, so pages 2 onwards are never foundUse <a href> links to real URLs
Page number in a fragment, such as #page=2Everything after # is ignored, so all pages are one URLPut the page in the path or a query parameter
Every page canonicalised to page 1Google may drop pages 2 onwards and the items linked from themGive each page a self-referencing canonical
noindex on pages 2 onwardsOver time those pages are crawled less and their links followed lessLeave paginated pages indexable
Infinite scroll with no URLsOnly the first batch exists for crawlersBack the scroll with paginated URLs
Pages beyond the last return 200Endless empty pages, a crawler trapReturn 404 for out-of-range pages
Sort and filter parameters on every pageThousands of combinations of the same listCanonical to the unfiltered page, limit crawlable combinations

The last two rows overlap with wider crawl issues. See crawler traps and faceted navigation for those.

How to add pagination in HTML

Whatever builds the page, the HTML a crawler receives for page 3 should look like this:

<head>
  <title>Sourdough Recipes, Page 3 | Example Bakery</title>
  <link rel="canonical" href="https://example.com/recipes/?page=3">
</head>
...
<nav aria-label="Pagination">
  <a href="/recipes/?page=2" rel="prev">Previous</a>
  <a href="/recipes/">1</a>
  <a href="/recipes/?page=2">2</a>
  <a href="/recipes/?page=3" aria-current="page">3</a>
  <a href="/recipes/?page=4">4</a>
  <a href="/recipes/?page=21">21</a>
  <a href="/recipes/?page=4" rel="next">Next</a>
</nav>

Use a self-referencing canonical on each page as described in how to fix canonicals, and make sure pages beyond the last return a real 404 status.

Implementing it on the server, and does pagination improve performance?

Yes, pagination improves performance for both the visitor and the server. A page of 24 products sends a fraction of the HTML and images of a page with 500, and the database returns a small slice. The usual query uses LIMIT and OFFSET:

SELECT id, title, slug, published_at
FROM posts
WHERE status = 'published'
ORDER BY published_at DESC, id DESC
LIMIT 24 OFFSET 48;   -- page 3

Offsets are fine for a few hundred pages. On very large tables they slow down as the page number rises, because the database still reads and discards every skipped row. For deep lists and APIs, keyset pagination, also called cursor pagination, starts from the last item seen instead:

SELECT id, title, slug, published_at
FROM posts
WHERE status = 'published'
  AND (published_at, id) < ('2026-03-14 09:00:00', 4812)
ORDER BY published_at DESC, id DESC
LIMIT 24;

Keep an index on the sort columns, here published_at and id. Always include a unique column in the sort order so items with the same date do not jump between pages. For public, crawlable listings, keep numbered page URLs even if you use keyset queries behind them; cursor tokens in URLs make poor, unstable addresses.

Return the right status codes

curl -sI "https://example.com/recipes/?page=3"   | head -n 1   # expect 200
curl -sI "https://example.com/recipes/?page=999" | head -n 1   # expect 404
curl -sI "https://example.com/recipes/?page=1"   | grep -i '^location'   # expect /recipes/

Pagination in WordPress, Shopify and Next.js

Infinite scroll and load more buttons

Infinite scroll is fine for visitors if it sits on top of normal pagination. Each batch should correspond to a real URL such as ?page=4, the page should update the address with history.pushState as the visitor scrolls into a new batch, and the paginated links should remain in the HTML, even if visually tucked below the list. A crawler then sees normal paged URLs while visitors scroll.

A worked example: a recipe archive

Example Bakery's recipe section had 500 recipes, 24 per page, across 21 pages. A crawl found only 62 recipes reachable from internal links, and Search Console listed most of the rest as Discovered, currently not indexed or did not know about them at all.

The page links were <button> elements that loaded the next batch with JavaScript, every page had a canonical pointing to /recipes/, and pages 2 onwards carried noindex, follow. Requesting ?page=999 returned an empty page with status 200.

The fix replaced the buttons with anchors to ?page=N, kept the JavaScript as an enhancement, changed each canonical to the page's own address, removed the noindex, and returned 404 for out-of-range pages. A recrawl reached all 500 recipes within three clicks of the recipe index, and over the following weeks the number of indexed recipes rose steadily.

The fix, step by step

Step 1

Map your paginated listings

List every template that paginates, such as blog archives, categories, collections, tag pages and internal search results. For each, note the URL pattern for page 2, the number of items per page and the total number of pages. Then pick one deep item from the last page of each listing. This map tells you which templates to fix and gives you test items to check later, because reaching those deep items is the whole point of crawlable pagination.

Step 2

Give every page a real URL

Make sure each page in a series has its own address, using a path such as /page/3/ or a query parameter such as ?page=3, never a fragment after a hash. Redirect ?page=1 to the clean listing address with a 301. Confirm by opening page 3 directly in a private browser window: it should load the third slice of items without needing you to visit pages 1 and 2 first.

Step 3

Use crawlable anchor links

Replace any page controls built from buttons, onclick handlers or scripts with plain <a href> links to the real page URLs. Include previous and next links, the first and last page, and a few page numbers around the current one. JavaScript can still improve the behaviour on top. Confirm by fetching page 2 with curl and finding anchors with href values for pages 1 and 3 in the raw HTML.

Step 4

Set self-referencing canonicals

Change the canonical tag on each paginated page so it points at that page's own URL, including the page number, instead of page 1. Keep the canonical free of sort and tracking parameters. In WordPress and Shopify this usually comes from the SEO plugin or theme template. Confirm by fetching pages 2 and 3 with curl and checking that each canonical matches the address you requested.

Step 5

Remove noindex from pages 2 onwards

Check the robots meta tag and the X-Robots-Tag header on pages 2 and later, and remove any noindex added by a plugin or template. Paginated pages should be indexable so Google keeps crawling them and following their links to items. Confirm with URL Inspection in Search Console on page 2, using Test live URL, which should report that the page can be indexed.

Step 6

Return 404 beyond the last page

Add a check that compares the requested page number with the total number of pages, and return a 404 status when it is too high, zero, negative or not a number. Do not show an empty listing with status 200. Confirm by requesting ?page=999 with curl -I and checking the first line shows 404, and that a valid last page still returns 200 with items on it.

Step 7

Back infinite scroll with pages

If the listing uses infinite scroll or a load more button, tie each batch to a page URL, update the address with history.pushState as each batch appears, and keep the numbered pagination links in the HTML. Load the right batch when a page URL is opened directly. Confirm by opening ?page=4 in a fresh tab and checking that it shows the fourth batch, then fetching it with curl.

Step 8

Keep the queries fast

Check the query behind each listing. Add an index on the sort columns, include a unique column such as id in the sort order so items do not move between pages, and consider keyset pagination for very deep lists. Measure the response time of page 1 and the last page. Confirm the last page responds about as quickly as the first, and well within one second on your server.

Step 9

Crawl and confirm deep items

Run a crawl of the site starting from the homepage and check that every page in each series is found and that the deep test items you noted in step one are reached. Check how many clicks they are from the homepage. Then submit the sitemap and use URL Inspection on a few deep items. Rising indexed counts over the following weeks show the pagination is now working.

Edge cases worth knowing

Keeping pagination crawlable

Pagination tends to break during redesigns, when a new theme or front-end component swaps links for a load more button. Protect it with a few checks:

  1. After any template change, fetch page 2 of a listing with curl and confirm the pagination links are anchors with href values and the canonical points at page 2.
  2. Test a page number past the end and confirm it returns 404.
  3. Crawl the site every few months and compare the number of items found with the number published. A gap usually means a break in pagination or in internal links.
  4. Keep every item in the XML sitemap, so discovery never depends on pagination alone.
Questions and answers

1. What is pagination on a website?

Pagination is the practice of splitting a long list of content, such as blog posts, products or search results, across several numbered pages, with links to move between them. Each page shows a fixed number of items and has its own URL, for example page 2 of a blog archive. It keeps pages fast to load and easy to use, and for search engines it provides the links that lead to older posts and deeper products that are not linked from anywhere else.

2. How does pagination work?

Pagination works by reading a page number from the URL, calculating which slice of items belongs on that page, and returning only those items with links to the other pages. With 24 items per page, page 3 skips the first 48 items and shows the next 24. The server or framework usually does this with a database query using a limit and an offset, or a cursor, and it calculates the total number of pages from the item count.

3. Does pagination improve performance?

Yes, pagination usually improves performance, because each page sends less HTML, fewer images and less data than one long list, and the database returns a small slice instead of every row. Visitors see the first items sooner and phones do less work. The main catch is that offset queries slow down on very deep pages of very large tables, because skipped rows are still read. Indexes on the sort columns and keyset pagination solve that for large catalogues and APIs.

4. Should paginated pages have a canonical to page 1?

No, each paginated page should have a canonical pointing at itself, including its page number. Pointing pages 2 onwards at page 1 tells Google they are copies of page 1, which they are not, because they list different items. Google may then drop them and crawl the items they link to less often. The only exception is when a fast view all page exists, in which case the paginated pages can point their canonicals at that view all page.

5. Should I noindex paginated pages?

No, in most cases you should leave paginated pages indexable. A noindex does not stop Google crawling a page at first, but pages left on noindex for a long time tend to be crawled less often and their links followed less, which is the opposite of what pagination is for. Paginated pages rarely compete with your main pages in search results. If they appear for searches where you want page 1 to rank, improve page 1 rather than hiding the rest.

6. Is infinite scroll bad for SEO?

Infinite scroll is not bad for SEO if it is backed by real paginated URLs, but on its own it usually is. Crawlers do not scroll, so content loaded only when a visitor reaches the bottom of the page is often never seen. The fix is to give each batch its own URL, update the address as the visitor scrolls, load the right batch when that URL is opened directly, and keep normal pagination links in the HTML for crawlers and visitors without JavaScript.

7. How many items should each paginated page show?

There is no single correct number, but between 20 and 50 items per page suits most blogs and shops, and 24 or 25 is a common choice. Fewer items create more pages and push older content deeper, while very long pages load slowly on phones. Choose a number that keeps the page fast and the series reasonably short, then keep it stable. Changing it later moves every item to a different page number, so out-of-range pages must then return 404.

Check that crawlers reach every paginated page

The Site Crawler follows your pagination links the way a search engine does and reports pages it cannot reach, canonicals that point to page one, noindex tags and out-of-range pages that return 200.

Open Site Crawler Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Site Crawler Fixes  ·  Crawler traps  ·  Category pages  ·  Orphan pages  ·  Crawl budget  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.