# HP4002: A browser extension changed the page

> HP4002 (extension-mutation) means a browser extension such as a grammar checker or password manager changed the page before hydration. When to ignore it.

Source: https://hydration.jscrate.dev/docs/issues/hp4002
Last updated: 2026-09-18

HP4002 (`extension-mutation`) means the page changed before hydration in a way
typical of browser extensions: grammar checkers, password managers, dark mode
tools. It is an info finding, because there is nothing to fix in your code.
Ignore it when it is expected, for example when your scenario simulates an
extension.

| | |
| --- | --- |
| Code | `HP4002` |
| Name | `extension-mutation` |
| Default severity | Info |
| Group | Changes made outside React |
| What it means | Changes typical of browser extensions (grammar checkers, password managers, translators) were found. |

## What the HP4002 extension mutation finding means

It comes from the same comparison as [HP4001](https://hydration.jscrate.dev/docs/issues/hp4001): the DOM the
browser parsed from the server HTML against the DOM right before React
hydrated. A change counts as an extension's when it:

- adds an attribute extensions are known for: `data-new-gr-c-s-check-loaded`,
  `data-gr-ext-installed` and `data-gramm` (Grammarly), `data-lt-installed`
  (LanguageTool), password manager and Dark Reader attributes,
  `data-ms-editor`, `cz-shortcut-listen` or `bis_*`;
- or inserts a custom element (a tag with a dash, such as
  `<grammarly-desktop-integration>`) directly into `<html>` or `<body>`.

Other changes an extension makes, such as a translator rewriting text, look like
any other script and are reported as HP4001.

Playwright starts the test browser with a clean profile, so HP4002 usually
means a scenario simulates an extension with `initScripts`, or the run uses a
browser profile that has extensions installed.

## The React warning your users see

Real users do have these extensions. In a React 18 development build, the
attributes a grammar checker adds to `<body>` produce this warning:

```text
Warning: Extra attributes from the server: data-new-gr-c-s-check-loaded,data-gr-ext-installed
```

[Extra attributes from the server](https://hydration.jscrate.dev/docs/errors/extra-attributes-from-the-server)
explains it. React 19 reports the same situation as
[attributes that didn't match](https://hydration.jscrate.dev/docs/errors/tree-hydrated-but-attributes-didnt-match).

## Likely causes

- [A browser extension](https://hydration.jscrate.dev/docs/causes/extension) in the test browser's profile.
- A scenario that simulates one on purpose, to check that the page survives it.

## How to fix it

This comes from a browser extension on the test machine or simulated by your
scenario; ignore it if it is expected.

1. If you did not expect it, test with a clean browser profile: the default
   Playwright browser has no extensions.
2. If you simulate an extension on purpose, ignore its attributes, so they are
   never compared, or ignore the code with a reason (below).
3. If the warning in your own console bothers you, `suppressHydrationWarning`
   on `<body>` stops React from reporting that element's own attributes. It
   does not cover anything inside `<body>`.

```ts title="hydration-proof.config.ts"
import { defineConfig } from "hydration-proof";

export default defineConfig({
  ignore: {
    attributes: [/^data-gr-/, "data-new-gr-c-s-check-loaded"],
    issues: [
      { code: "HP4002", reason: "The extensions scenario simulates Grammarly" },
    ],
  },
});
```

Info findings do not fail the run and are not printed in the terminal list;
the HTML and JSON [reports](https://hydration.jscrate.dev/docs/reports) show them. See
[ignoring findings](https://hydration.jscrate.dev/docs/ignoring) for every way to silence one.

## Related

- [HP4001: the page was modified before React hydrated](https://hydration.jscrate.dev/docs/issues/hp4001)
- [HP4003: HTML rewritten by a CDN or proxy](https://hydration.jscrate.dev/docs/issues/hp4003)
- [Hydration errors caused by browser extensions](https://hydration.jscrate.dev/docs/causes/extension)
- [Scenarios and initScripts](https://hydration.jscrate.dev/docs/scenarios)
- [HP6001: a mismatch hidden by suppressHydrationWarning](https://hydration.jscrate.dev/docs/issues/hp6001)
