# CSR vs SSR: which rendering is better for SEO and speed?

> CSR vs SSR is the choice between building the page in the visitor's browser or on the server. For pages that must rank, server-side rendering or static generation wins; client-side rendering suits pages behind a login. How each works, what it does to crawling and Core Web Vitals, and how to choose per page.

Updated 2026-09-26 · Technical SEO · HTML version: https://getreport.app/guides/ssr-vs-csr-seo

CSR vs SSR is the choice between building a page's HTML in the visitor's browser (client-side rendering) or on the server before it is sent (server-side rendering). For SEO the answer is clear: pages that must rank should reach crawlers as finished HTML, which SSR and its build-time cousin, static site generation (SSG), deliver and CSR does not. For speed it depends on the page, and for a logged-in dashboard CSR is fine. This guide explains how each approach works, what it changes for Google, AI crawlers and Core Web Vitals, and how to pick per page type. It is part of our guide to [JavaScript SEO for sites built with scripts](https://getreport.app/guides/javascript-seo).

## Quick answer

- **CSR:** the server sends an almost empty HTML file and a script; the browser builds the page. Crawlers that do not run JavaScript see nothing, and Google sees the content only after a later rendering step.
- **SSR:** the server builds the full HTML for each request. Every crawler sees the content at once; the server does more work.
- **SSG:** the HTML is built once at deploy time and served as files. Complete HTML and the fastest response, for pages that are the same for everyone.
- **Hydration** combines them: server or static HTML first, then JavaScript makes it interactive. This is what modern frameworks do by default.
- **Pick per page:** SSG for pages that change with deploys, SSR for fresh or personalised data, CSR only where nobody searches.
- Check which one a page uses with the free [JavaScript SEO check](https://getreport.app/tools/js-rendering-check).

## How client-side rendering works

With CSR, the first response is a shell:

```html
<body>
  <div id="root"></div>
  <script src="https://getreport.app/assets/app.3f9c1a.js" type="module"></script>
</body>
```

The browser downloads the script, runs it, fetches data from an API and builds the DOM. Until that finishes, the visitor sees a blank page or a spinner. Every later navigation happens in the browser without a new HTML request, which feels fast once the app has loaded.

Frameworks produce this by default when used without a server layer: React with Vite (or the deprecated Create React App), Vue without Nuxt, Angular without `@angular/ssr`, and React Router or Nuxt with server rendering switched off.

## How server-side rendering works

With SSR, the server runs the same components, fetches the data and sends complete HTML:

```html
<body>
  <main>
    <h1>Blue trail runner</h1>
    <p>Lightweight trail shoe with a 6 mm drop, 89 EUR.</p>
    <!-- … -->
  </main>
  <script src="https://getreport.app/assets/app.3f9c1a.js" type="module"></script>
</body>
```

The browser shows the content as soon as the HTML arrives, then downloads the script and **hydrates** the page: it attaches event handlers to the existing HTML instead of rebuilding it. Next.js, Nuxt, SvelteKit, Remix and React Router's framework mode, and Angular with `@angular/ssr` work this way.

**SSG** does the same rendering once, at build time, and saves each page as a file. **Incremental static regeneration (ISR)**, or stale-while-revalidate caching, rebuilds individual pages in the background after a set time, which suits large catalogues.

## CSR vs SSR compared

| | CSR | SSR | SSG |
| --- | --- | --- | --- |
| Where HTML is built | Browser | Server, per request | Build server, once |
| What crawlers get first | Empty shell | Complete page | Complete page |
| Google indexing | After rendering, which can be delayed or fail | Immediate | Immediate |
| AI crawlers and link previews | See nothing | See everything | See everything |
| Time to first byte | Fast (static file) | Slower: waits for data and rendering | Fastest (static file, cacheable at the edge) |
| Largest Contentful Paint | Late: waits for script and data | Early | Earliest |
| Interaction to Next Paint | Depends on bundle size | Depends on hydration cost | Depends on hydration cost |
| Server cost | Lowest | Highest | Low (build time grows with page count) |
| Fresh or personal data | Yes | Yes | No, only what existed at build time |

### SEO

For SEO, the difference is what the first HTML response contains. Google processes JavaScript pages in three steps (crawl, render, index), and the render can come seconds or much later, as the guide on [how Google renders JavaScript content](https://getreport.app/guides/javascript-rendered-content-and-google) explains. With CSR, everything that matters waits for that step: text, internal links, structured data and often the title. If an API call fails or needs a cookie, Google indexes the empty state.

Google is also the best case. Most AI crawlers do not run JavaScript, and neither do the link previews in Slack, WhatsApp and LinkedIn, so a CSR page is blank to them. Google's own documentation recommends server-side rendering, static rendering or hydration, and calls serving a separate prerendered version to bots a workaround; our guide to [dynamic rendering and prerendering](https://getreport.app/guides/dynamic-rendering-and-prerendering) covers that option.

SSR and SSG remove the dependency. Head tags, content and links are all in the first response, for every reader.

### Speed and Core Web Vitals

CSR's first byte is fast, because the server only sends a static file, but everything visible depends on what comes after: download the bundle, parse and run it, fetch the data, render. That chain usually makes the **Largest Contentful Paint** late, especially on mid-range phones. Our guide to [fixing Largest Contentful Paint](https://getreport.app/guides/fix-largest-contentful-paint) breaks down the phases.

SSR moves work to the server, so **time to first byte** rises by however long the data fetches and rendering take. It pays off because the content is visible as soon as the HTML arrives. Streaming SSR, which sends the page shell first and fills in slow parts as they resolve, reduces the wait. A slow SSR server can still cancel out the benefit; the guide to [slow server responses](https://getreport.app/guides/ttfb-what-a-slow-server-looks-like) shows what that looks like.

SSG usually wins on both: files served from a CDN, with content in them.

All three can suffer on **Interaction to Next Paint**. Hydration runs the whole component tree in the browser, and a large bundle creates [long tasks on the main thread](https://getreport.app/guides/long-tasks-and-main-thread-work) that delay the first clicks. Partial or incremental hydration, islands architectures (Astro) and React Server Components reduce how much JavaScript has to run.

## Which should you use?

Decide per page type, not per site. Most frameworks let you mix modes route by route.

| Page type | Recommended | Why |
| --- | --- | --- |
| Home, landing and marketing pages | SSG | Same for everyone, changes with deploys |
| Blog posts, articles, docs | SSG (or ISR) | Content changes rarely |
| Category and product pages | SSR, or SSG with ISR | Prices and stock change; must rank |
| Search results pages on your site | SSR, usually `noindex` | Endless combinations |
| Account, cart, checkout | CSR or SSR | Personal; nobody searches for them |
| Dashboards and tools behind a login | CSR | No crawler can reach them anyway |

If you are on a client-rendered app today, you do not have to rewrite everything. Move the public routes to a framework with SSR or SSG first and leave the logged-in app as it is. The framework guides show how: [Next.js SEO](https://getreport.app/guides/nextjs-seo), [React SEO](https://getreport.app/guides/react-seo), [Angular SEO](https://getreport.app/guides/angular-seo) and [Vue and Nuxt SEO](https://getreport.app/guides/vue-nuxt-seo).

## How to tell which rendering a page uses

Three quick checks, from simplest to most complete:

1. **View source** (not the Elements panel). If the main text is there, the page is server-rendered or static. If you see an empty `<div id="root">` or `<app-root>`, it is client-rendered.
2. **`curl`** the page and search for a sentence from the main text: `curl -s https://example.com/page/ | grep -c "a sentence from the page"`. A result of `0` means the text is added in the browser.
3. **Compare raw and rendered HTML** with the check below, which also shows head tags that change after load.

> **Free tool:** [JavaScript rendering checker: raw vs rendered HTML](https://getreport.app/tools/js-rendering-check): Free JavaScript rendering checker: compare raw HTML with the rendered page and see which text, links, tags and structured data appear only after scripts run.

The check fetches the page as raw HTML, renders it in Chromium, and compares title, description, canonical, robots, headings, links, word count and JSON-LD. A client-rendered page shows a large share of text only in the rendered column; a server-rendered one shows nearly identical columns. The full report runs the same comparison:

> **Check: The visible text is present without JavaScript.** Google renders JavaScript later and with a budget, so text that only appears after scripts run can be indexed late or not at all. Other search engines and link previews may never see it.
>
> 1. Serve the main content in the HTML (server-side rendering or static generation) and use JavaScript only to enhance it.
> 2. Check the difference in the technical detail; menus and widgets are fine, headlines and body copy are not.

For the speed side, the [website speed test](https://getreport.app/tools/speed-test) shows TTFB, LCP and INP for the same page, so you can see whether SSR's slower first byte is paying for itself.

## Common mistakes

- **Assuming SSR because the framework supports it.** Many frameworks let you switch it off per route or globally; check what the page actually sends.
- **SSR with client-side data fetching.** The shell is rendered on the server, but the content still loads in the browser.
- **Blocking the whole response on the slowest API.** Stream the page or cache the data so SSR does not trade a late LCP for a late first byte.
- **Rendering different content on server and client,** which causes hydration errors and layout shifts.
- **SSG for data that changes hourly,** without ISR or revalidation, so crawlers index stale prices.
- **Choosing CSR for a content site** to save server cost, then adding a prerendering service to fix SEO.

## Questions people ask

### Is server-side rendering necessary for SEO?

Not strictly, but it is the safest choice for pages that must rank. Google can render client-side pages, later and less reliably, while most AI crawlers and link previews cannot render them at all. Server-side rendering or static generation puts the content, links and head tags in the first response for every reader. For pages behind a login, client-side rendering is fine because nobody needs to index them.

### Is SSR faster than CSR?

Usually for what visitors see first. SSR's first byte arrives later, because the server fetches data and renders, but the content appears as soon as the HTML lands, while CSR has to download and run its script and fetch data before showing anything. That often makes Largest Contentful Paint earlier with SSR. Static generation is typically faster than both. After the first load, CSR navigation between views can feel quicker.

### What is the difference between SSR and SSG?

Timing. Server-side rendering builds the HTML on each request, so it can include fresh or personal data. Static site generation builds it once at deploy time and serves the same file to everyone, which is faster and cheaper but only as fresh as the last build. Incremental regeneration sits in between, rebuilding individual static pages in the background. All three give crawlers complete HTML.
