PWA SEO: why a crawler always sees your progressive web app as a first-time visitor, and the five fixes that follow
How service workers, the app shell, the manifest and offline pages affect search, from web.dev's PWA course and Google Search Central as read on 22 October 2026.
Published by AI Knows Us · Updated 21 October 2026
A progressive web app can rank as well as any website, because a PWA is a website. The difference that matters for SEO is that the clever parts of a PWA, the service worker, the cache and the installed app window, only work for a returning user. A search crawler never gets them. Google's documentation says its renderer "does not retain state across page loads", and web.dev's PWA course says that the first time a user opens a PWA, "all its network requests go directly to your server". So the rule for PWA SEO is simple: whatever your server sends on a first visit, with no service worker and no cache, is your page as far as search is concerned. Get that response right and the PWA features become a bonus for users, not a risk for rankings.
What makes a PWA different from an ordinary site
web.dev, the developer site written by members of Google's Chrome team, describes a PWA as "a website" whose assets are the same as on the web, "but with new tools to make those assets load fast when online and available when offline." The tools are:
- A service worker. A script that sits between the app and the network, intercepts requests in its scope, and can answer them from the Cache Storage API, from the network, or by building the response itself.
- A web app manifest. A JSON file with the app's name, icons, display mode and start URL. web.dev says a manifest is required for installability in every browser, although Chrome may still allow installation without one.
- Installability. The app can run in its own window, without the browser's address bar.
None of these is a ranking feature. They are about speed, offline use and the installed experience. The SEO question is whether they change what a crawler receives.
Why the crawler is always a first-time visitor
Two facts from two Google sources settle this. web.dev says a service worker "won't be available on first load or while it's waiting to activate", and that by default an activated service worker "can't manage the page that registered it" until the next navigation. Google Search Central says its Web Rendering Service clears Local Storage, Session Storage and HTTP cookies across page loads. So plan as though every crawl is a first visit: no installed service worker, nothing cached on the device, no stored login.
web.dev gives the same advice for users: treat the service worker "as optional and not requiring it for core features". Follow that for people and you have followed it for search too.
Fix 1: put the content in the first response, not only in the app shell
Many PWAs are single-page apps built on an app shell: the server sends a thin HTML frame, and JavaScript fetches and draws the content. Google's JavaScript SEO basics describe exactly this model, where "the initial HTML does not contain the actual content and Google needs to execute JavaScript before being able to see the actual page content." Google can render JavaScript, but the same page adds that "server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript."
web.dev's architecture chapter makes the same trade explicit. It says a multi-page app usually sends "pre-rendered HTML" to the browser, and that this suits apps centred on "views of a single piece of data", naming news and e-commerce. A single-page app suits things like dashboards and editors. It also says you can mix the two, for example with store listings as a multi-page app and the checkout as a single-page app. For SEO that split is usually right: the pages you want found are server-rendered, and the app-like parts behind them can be client-side. Our guide to JavaScript SEO and how Google renders a site covers the rendering choices in more depth.
Fix 2: give every view a real URL and a real status code
An installed PWA hides the address bar, so it is easy to forget that each view still needs its own URL. Google's guidance for single-page apps:
- Use the History API for routing. Google says not to use URL fragments such as
#/productsto load different content, and that the old AJAX crawling scheme has been deprecated since 2015. - Return proper status codes. Google warns that single-page apps handling errors in client-side JavaScript "often report a 200 HTTP status code instead of the appropriate status code", which can get error pages indexed. Return 404 from the server, or add a
noindexrobots meta tag with JavaScript on the error view.
Fix 3: keep the offline page out of the index
A good PWA shows a friendly offline page when the network fails. That page is served by the service worker from the cache, so a crawler, which has no service worker, never receives it in place of your content. The risk is the other way round: if your offline page also exists as a normal URL on the server, such as /offline, it can be crawled like any other page. Add a noindex robots meta tag to it, and keep it out of your sitemap.
Fix 4: fingerprint your files so Google renders the current version
Service workers and long caching go together, and Google has its own caching behaviour to account for. Its JavaScript troubleshooting page says Googlebot "caches aggressively" and that its renderer "may ignore caching headers", which can lead it to use outdated JavaScript or CSS. Google's fix is content fingerprinting: put a hash of the file's content in its name, like main.2bb85551.js, so every change produces a new filename. Most build tools do this already. Check that your service worker's precache list uses the same fingerprinted names.
Fix 5: do not make the content wait for a permission or a socket
PWAs often ask for permissions early: notifications, location, camera. Google says to "Expect Googlebot to decline user permission requests". If a page shows nothing until the user answers a location prompt, Googlebot sees nothing. Google also says Googlebot retrieves content over HTTP and "does not support other types of connections, such as WebSockets or WebRTC". A PWA that streams its main content over a socket needs an HTTP fallback for the first load.
| PWA feature | What a crawler gets | What to do |
|---|---|---|
| Service worker cache | Nothing; it fetches from your server | Make the server response complete on its own |
| App shell with client rendering | An empty frame until JavaScript runs | Server-render or pre-render the pages you want found |
| Offline page | Only if it also exists as a server URL | noindex it and leave it out of the sitemap |
| Permission prompts | A declined prompt | Show content without waiting for permission |
| Manifest start URL | Opens the installed app, not a search result | Keep tracking parameters off internal links |
A note on the manifest's start URL
Teams often add a tracking parameter to the manifest's start_url, such as ?source=pwa, to count launches from the home screen. That address opens inside the installed app, not in search results, so it is harmless on its own. Keep the same parameter out of links inside your pages, because Google's URL guidance lists referral parameters as a source of duplicate URLs. web.dev adds a practical warning: changing the start_url later can stop the browser recognising that the app is already installed, so choose it once.
The visitor that never installs anything
AI assistants fetch pages the way search crawlers do: one request, no installed service worker, nothing cached. An assistant crawler that does not run your JavaScript sees only the first HTML, so a PWA whose product pages arrive as an empty app shell can be invisible to it even when Google has rendered the page. Once your first-visit HTML carries the content, it is worth checking the result from the other side: ask ChatGPT, Gemini or Perplexity the question your users ask and see whether your app is named. AI Knows Us runs those questions for a business and records which pages each assistant reads and cites.
Questions about PWA SEO
Is a PWA good or bad for SEO?
Neither. A PWA is a website, and it ranks on the same content and the same first response as any other site. It helps when the service worker makes repeat visits fast, and it hurts only when the content depends on JavaScript, a cache or a permission that a crawler does not have.
Does Googlebot use my service worker?
Plan as if it does not. Google says its renderer keeps no state between page loads, and web.dev says a service worker does not control the first load, so the crawler gets your server's response.
Should a PWA be a single-page app or a multi-page app for SEO?
web.dev says either is a valid way to build a PWA, and that you can mix them. For search, server-render the pages you want found and keep app-like features client-side.
Does the web app manifest help rankings?
The manifest tells the browser how to display your app when it is installed: its name, icons, display mode and start URL. It is about installation. What ranks is the content your server sends for each URL.