Infinite Scroll SEO

How to implement infinite scroll without losing your indexing — why Googlebot doesn't scroll, the tall-viewport render trick that flattens two pages into one, the paginated-URL + History API fix, and the ecommerce category-page case.

First published: Jul 3, 2026 · Last updated: Jul 18, 2026 · Advanced

Infinite scroll loads more content as you scroll, instead of via numbered pages — and Googlebot never scrolls or clicks, so anything gated behind that action is invisible by default. Google renders in a very tall viewport (about 411×12,140px mobile, 1024×9,307px desktop) as a workaround, but that same tall viewport can trigger the scroll loader during rendering and fold two logical pages into one indexed URL — a failure mode where a 'not indexed' page is actually indexed as part of another. The fix is architectural: give every chunk a real, persistent, absolute URL (like ?page=2), link them with crawlable anchors, and update the address bar with the History API as the user scrolls. rel=next/prev is legacy (Google dropped it in 2019; Bing still supports it). On ecommerce category pages, back it all with sitemaps or a Merchant Center feed and verify in the URL Inspection Tool's rendered HTML. A production build also needs a real popstate/back-forward contract, distinct loading/error/end states, and deliberate accessibility — none of that comes for free just because the indexing fix is in place.

TL;DR — GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. never scrolls and never clicks, so scroll-gated content is invisible by default. Google’s workaround is to render in a very tall viewport (roughly 411×12,140px mobile, 1024×9,307px desktop) — but that same height can trigger the scroll loader during renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., folding the next logical page into the current one so two pages get indexedStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. as a single URL. The durable fix is architectural: persistent, absolute, per-chunk URLs (e.g. ?page=12), linked with crawlable anchors, with the History API updating the address bar as each chunk becomes primary. rel=next/rel=prev is legacy for Google (dropped 2019) but still respected by Bing. On ecommerce PLPs, sitemapsA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. or a Merchant CenterGoogle Merchant Center (GMC) is a free platform where retailers upload and manage product data so their products can appear across Google — Shopping, organic Search product grids, Images, Lens, and AI surfaces. Since 2020 it powers free (organic) product listings, not just paid Shopping ads. feed are a discovery backstop. Verify everything in the URL Inspection ToolA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version.’s rendered HTML.

Evidence for this claim Google Search does not generally interact with scrolling controls, so infinite-scroll content needs crawlable paginated URLs. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Lazy-loaded content Evidence for this claim The History API can update URLs for loaded page chunks without a full navigation. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: History API

First, a disambiguation

If you search “Google infinite scrollInfinite scroll is a loading pattern where content appears automatically as a user scrolls, instead of via numbered pages. Because Googlebot doesn't scroll or click, indexable infinite scroll needs real per-chunk URLs (paginated loading) that update via the History API — otherwise deep content may never be crawled, or worse, get merged into the wrong page.” you’ll hit results about Google’s own continuous scroll on its search results pages — a SERP featureSERP features are any element on a search results page beyond the classic ten blue links — featured snippets, People Also Ask, knowledge panels, sitelinks, image and video packs, AI Overviews, and structured-data-driven rich results. Google documents that losing rich-result eligibility doesn't affect ranking; their SEO relevance is CTR (they redistribute clicks). Some are unlocked by markup; most are purely algorithmic. Google turned on and then discontinued in mid-2024. That’s a Google-product UX decision and has nothing to do with how GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. crawls your site. This article is about the latter: infinite scroll as a loading pattern on your own pages, and whether Google can index what it loads.

The core constraint: Google doesn’t interact with your page

Everything here follows from one fact. Google’s own lazy-loading docs say the recommended patterns “don’t rely on user actions, such as scrolling or clicking, to load content, which is important as Google Search does not interact with your page.” The paginationPagination splits a large set of content — product listings, blog archives, search results — across multiple sequentially numbered URLs. For SEO, each paginated page should be crawlable, indexable, and self-canonical; Google no longer uses rel=prev/next, but Bing still does. doc says it even more plainly: “Google’s crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. don’t ‘click’ buttons and generally don’t trigger JavaScript functions that require user actions to update the current page contents.”

As I put it in my own JavaScript SEO guide: “Googlebot doesn’t take action on webpages. It’s not going to click things or scroll, but that doesn’t mean it doesn’t have workarounds. As long as content is loaded in the DOM without a needed action, Google will see it. If it’s not loaded into the DOM until after a click, then the content won’t be found.”

So infinite scroll that only triggers on a real scroll event is a content-discovery problem before it’s anything else.

Google’s workaround: a very tall viewport

Google doesn’t simulate scrolling. Instead it renders your page in an unusually tall viewport, so content a few screens down is already inside the rendered area without anyone scrolling. The earliest on-record hint of this was John Mueller’s 2017 note that “Googlebot renders with a very tall viewport, which skews some CSS (often images). Try in Chrome dev-tools, eg 9000px high viewport.”

The specific numbers I’ve documented: for mobile, Google loads the page at a screen size of 411×731 pixels and resizes the length to 12,140 pixels — “essentially, it becomes a really long phone with a screen size of 411×12140 pixels. For desktop, it does the same and goes from 1024×768 pixels to 1024×9307 pixels.” (I haven’t seen recent re-tests of those exact figures, and they may vary with page length; the original dimensions trace back to independent testing by SEO researcher JR Oakes.) The point isn’t the exact pixel count — it’s that Google fakes “seeing far down the page” with height, not with movement.

Treat both the exact pixel dimensions and the two-pages-merged behavior below as dated, implementation-specific observations rather than a stable platform contract — Google doesn’t publish an official spec for either number, and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. behavior can change. Don’t assume your site behaves the same way; confirm current behavior for your own URLs with the rendered-HTML test in the next section instead of taking these figures as a guarantee.

The failure mode nobody explains: two pages indexed as one

A height-triggered loader can fire during rendering and merge two logical pages under one indexed URL. Source: /technical-seo/javascript-seo/

A normal browser viewport stops after page one. Google's render viewport expands much taller, reaches the infinite-scroll trigger without a real user scroll, and appends page two into the same DOM. The merged DOM is then indexed as one URL instead of two separate pages.

© Patrick Stox LLC · CC BY 4.0 ·

Here’s where the tall viewport bites back. Because the render viewport is so tall, the scroll-triggered loader can fire during rendering even though nothing “scrolled” in the human sense — the sheer DOM height can be enough to satisfy an IntersectionObserver or a scroll-position check. When that happens, the loader appends the next logical page’s content into the current page’s render, and Google indexes the merged result as a single URL.

I’ve diagnosed this several times. From my JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. guide:

“Another issue I’ve seen with this setup is, occasionally, two pages get indexed as one. I’ve seen this a few times when people said they couldn’t get their page indexed. But I’ve found their content indexed as part of another page that’s usually the previous post from them.”

“My theory is that when Google resized the viewport to be longer, it triggered the infinite scroll and loaded another article in when it was rendering. In this case, what I recommend is to block the JavaScript file that handles the infinite scrolling so the functionality can’t trigger.”

John Mueller described the same mechanic from Google’s side in a 2022 office-hours session: Google renders with a high viewport, that “would trigger some amount of infinite scrolling,” and “we might have two or three of these pages loaded on one page with infinite scroll, but not everything.” (That office-hours quote is relayed via Search Engine Journal’s write-up, not confirmed against the primary recording.)

Two consequences fall out of this:

  1. There’s no guarantee of how much gets pulled in. Might be nothing extra, might be two or three pages, never reliably everything. Infinite scroll alone is not a dependable way to get deep content indexed.
  2. “Not indexed” can be a misdiagnosis. The missing page may not be missing at all — it may be indexed as part of an earlier URL. That needs a different fix than a normal indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. bug.

How to diagnose it

Use Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance.’s URL Inspection ToolA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. and read the rendered HTML, not the raw source. Google’s docs are explicit: “You can use the URL Inspection Tool in Search Console to see if all content was loaded. Check the rendered HTML to make sure your content is in the rendered HTML by looking for it in URL Inspection Tool.” Search the rendered HTML for content you expect to be on page 1 only. If you find content from page 2 (or the next article) sitting inside page 1’s render, you’ve reproduced the merge bug.

You can also replicate the tall viewport locally: open Chrome DevTools, set a very tall custom viewport (Mueller’s suggestion was ~9000px), and load the page to see whether your loader fires with no scrolling.

The fix: paginated URLs + the History API

The durable fix is architectural, straight from Google’s current lazy-loading doc. To make infinite scroll indexable, “make sure your website supports paginated loading of these chunks”:

  • “Give each chunk its own persistent, unique URL.”
  • “Ensure that the content shown on each URL remains the same every time it’s loaded in a browser” — Google suggests absolute page numbers like ?page=12.
  • “Avoid using relative elements like ?date=yesterday in these URLs” — an address that returns different content each load is unusable as a canonical.
  • “Link sequentially to the individual URLs so that search engines can discover the URLs in a paginated set” — real <a href> links, not click handlers.
  • “When a new page chunk is loaded in response to the user scrolling, and it becomes the primary visible element for the user, update the displayed URL using the History API.”

That last point is the elegant part. history.pushState() / replaceState() swaps the URL in the address bar as the user scrolls past each boundary — so the visible URL always matches the primary content, and the user can refresh, share, and link to exactly where they are. Meanwhile the crawlable ?page=N URLs exist independently, so Google can reach every chunk directly whether or not the renderer ever triggers the scroll.

Two implementation notes that matter:

  • Use IntersectionObserver (or native browser lazy-loading), not a raw scroll listener. It performs far better (no scroll-thrash) and it’s the “load when visible” mechanism Google endorses for deferred content.
  • Keep the paginated set discoverable independently of the JS. Real anchors in the DOM, and/or the ?page=N URLs listed in your XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags.. Whatever the renderer captures, the sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing.-and-links layer is your backstop.

If a live site is already exhibiting the merge bug and you need to stop the bleeding before you can rebuild, my blunt emergency fix is to block the JavaScript file that triggers infinite scroll in robots.txt so it physically can’t fire during rendering — buying time to ship the proper paginated-URL architecture.

The History API point above covers half the contract — updating the address bar as a chunk becomes primary. The other half is making sure every entry path back into that URL actually reconstructs the right content, not just the right scroll position:

  • Use pushState() when a chunk becomes the primary visible content for the first time — that’s a real navigation step, and it’s what makes the back button meaningful.
  • Use replaceState() for corrections that shouldn’t create their own back-button stop, like syncing the URL after a fast scroll past several chunks at once.
  • Listen for popstate and re-render (or re-fetch) the chunk that matches the URL in the event. The browser’s default back/forward behavior restores scroll position, not the dynamic list state your JavaScript built — if a user hits back after your loader appended 40 more items, you need to reconstruct which items belong on that page, not just scroll them there.
  • Don’t lean on automatic scroll restoration alone to solve this. It controls where the viewport lands, not what content is present — if the underlying list can change between visits (new products added, items out of stock), scroll position without content reconstruction can strand the user in the wrong context.

This is the same discipline the paginated-URL fix already depends on: a chunk’s URL has to return the content it promised on a fresh load, a refresh, and a Search-Console live test — not just the first time it’s fetched mid-scroll.

Loading, error, and end-of-results states

A production implementation needs more states than “loading” and “loaded”:

  • Initial load — the first chunk should already be in the raw HTML the server sends, not assembled entirely by JS after the fact.
  • Next-chunk loading — a visible in-progress indicator so users (and anyone testing with assistive tech) know a fetch is underway.
  • Empty — a distinct state for zero results, not a blank space that looks broken.
  • Error / retry — a failed fetch shouldn’t silently strand the page with no way to try again, and a retry shouldn’t duplicate or reorder items already on the page.
  • End of results — a clear signal, not an infinite spinner, once there’s nothing left to load.

None of this is Google-specific, but it’s the same reliability the paginated-URL fix depends on: if the loader can silently break mid-fetch, you can’t trust that any given crawl or user session actually captured the chunk it should have.

Accessibility and performance: two things infinite scroll doesn’t give you for free

Infinite scroll has no inherent Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. outcome, good or bad — it’s determined entirely by how you build it. Every appended chunk grows the DOM, and a large enough DOM raises layout and style-recalculation cost, so watch append cost, image loading, layout shift from content without reserved space, and long tasksAny main-thread task over 50 ms — the primary cause of INP regressions. as the list grows. On very long pages, consider virtualizing chunks that have scrolled far out of view (removing their DOM nodes) instead of letting the DOM grow unbounded.

Accessibility needs its own deliberate design, not an assumption that “it renders, so it’s fine”:

  • Keyboard users need to be able to reach new content — and the footer or end-of-page navigation — without the page silently growing out from under their tab order.
  • Screen reader users need new content announced without interrupting what they’re doing — a polite status region, not a disruptive alert, is the usual pattern.
  • The WAI-ARIA feed design pattern is built for exactly this case: article-level regions inside a feed container, with defined keyboard behavior for moving between items and for reaching content before and after the feed.
  • Focus shouldn’t silently jump or get lost when a new chunk loads.

None of this is optional cleanup. It’s the difference between infinite scroll that works for everyone and one that only works for a mouse user with JavaScript who never strays from the happy path.

The historical context: rel=next/prev is legacy

If you learned paginationPagination splits a large set of content — product listings, blog archives, search results — across multiple sequentially numbered URLs. For SEO, each paginated page should be crawlable, indexable, and self-canonical; Google no longer uses rel=prev/next, but Bing still does. years ago, you learned rel="next" / rel="prev". Google introduced them in 2011 and paired them with its original 2014 “infinite scroll search-friendly recommendations” (paginate the content, provide component pages). Then in 2019 Google announced it hadn’t been using those tags for years and formally dropped them. The pagination doc confirms it today: “In the past, Google used <link rel="next" href="..."> and <link rel="prev" href="..."> to identify next page and previous page relationships. Google no longer uses these tags, although these links may still be used by other search engines.”

So the current Google recipe is unique URLs + crawlable links + the History API — no rel=next/rel=prev required. But “other search engines” includes Bing, which still respects them, so there’s no harm in keeping them in your markup for cross-engine benefit and accessibility. Bing itself doesn’t publish infinite-scroll-specific guidance; its stance reduces to the general JS-rendering caution its team laid out — bingbotBingbot is Microsoft Bing's primary web crawler — the bot that discovers, fetches, and renders pages to build the Bing index. That index also powers Yahoo, DuckDuckGo, Ecosia, and Microsoft Copilot, so Bingbot's reach is far wider than Bing's own search-market share. can render JavaScript but “it is difficult for bingbot to process JavaScript at scale,” so a crawlable paginated fallback helps Bing for exactly the same reason it helps Google.

Ecommerce category pages: the highest-stakes case

The most common real-world infinite scroll is on ecommerce category / product listing pages (PLPs), and it’s where the risk costs actual money. If deep-catalog products past the first screenful never get indexed, they can’t rank, and you lose the long tail of product-level organic trafficVisitors from unpaid search results — it compounds without ad spend.. This is the same territory covered in depth in the category-page material — infinite scroll is one more reason those pages need a crawlable structure underneath the UX.

Two backstops matter here:

  • XML sitemaps listing every canonical product and paginated category URL, so discovery doesn’t depend on the renderer.
  • A Merchant Center product feed, which feeds Google product data independently of whatever the category page’s renderer captures.

Lumar’s analysis of top UK fashion retailers found infinite scroll to be, in their words, “the biggest loser when it comes to indexability and SEO friendliness” among the pagination patterns — a useful reminder that this isn’t a theoretical edge case, it’s the default failure mode of a very popular PLP UX. (Lumar’s specific percentage figures should be read from their live report before citing an exact number.)

Infinite scroll vs. pagination vs. load more

Google’s pagination doc frames three UX patterns and is honest about the tradeoffs. Infinite scroll “uses a single page for all content” and is “intuitive — the user just keeps scrolling,” but it “can lead to ‘scrolling fatigue’ because of unclear result size” and “can’t handle very large numbers of results.” Classic numbered pagination is the most robust for SEO because every page is inherently a real URL. “Load more” sits in between — fine if the button is (or wraps) a real link to a paginated URL, useless for SEO if it’s a pure click handler.

The decision isn’t “which is allowed” — all three are allowed. It’s “which UX do you want, and did you build the crawlable URL layer underneath it.” Mueller’s 2023 summary is the whole thing in one line: “if each piece or virtual page is also accessible and findable through a unique URL, generally it should be fine to have infinite scroll.”

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.