> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Address Screening

> What the React SDK shows when a wallet address fails sanctions screening, and how to change that copy.

> [card] Recommended: JavaScript SDK with React Hooks
>
> For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](https://docs.dynamic.xyz/docs/javascript/reference/react-quickstart.md) to get started.

Dynamic screens every wallet address that signs in to your environment against sanctions data, and blocks matches. Screening runs server-side during wallet verification, is always on, and needs no setup in the SDK. For what screening checks and how to run it on your own Chainalysis or TRM Labs key, see [Address Screening](https://docs.dynamic.xyz/docs/get-started/security/address-screening.md).

This page covers what your React app shows when an address is blocked.

## What the user sees

When verification returns a screening block, the SDK disconnects the wallet and renders its access-denied view inside the widget:

* **Title:** "This wallet can't access this site."
* **Body:** "Access was declined based on this site's security policy."
* **Action:** "Try another method", which returns the user to the wallet list.

The copy is generic. The same view renders for a sanctions match, a
risk rule in your own [screening policy](https://docs.dynamic.xyz/docs/policies/screening-policies.md),
and an address on your deny list, so it never states which one applied.

You do not need to catch an error or render a fallback. The view is part of the auth flow.

> [!NOTE]
>
> Keep any copy you write here neutral and final. The user usually cannot change a screening result, so offer a different wallet rather than a retry that will fail again.

## Changing the copy

Override the `dyn_no_access.screening` keys through the `locale` prop on `DynamicContextProvider`:

```tsx theme={"system"}
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';

<DynamicContextProvider
  settings={{
    environmentId: 'YOUR_ENVIRONMENT_ID',
    walletConnectors: [EthereumWalletConnectors],
  }}
  locale={{
    en: {
      dyn_no_access: {
        screening: {
          title: 'We could not verify this wallet',
          description:
            'Contact support@yourcompany.com if you believe this is a mistake.',
          button_text: 'Try another wallet',
          social_media_link_text: 'Why am I seeing this?',
          social_media_link_url: 'https://yourcompany.com/help/screening',
        },
      },
    },
  }}
>
  <App />
</DynamicContextProvider>
```

These keys drive the access-denied view for every screening provider and for your own screening policies, which is why the default copy names none of them.

> [!NOTE]
>
> This key was previously named `dyn_no_access.chainalysis`. Overrides written
> against the old name still apply, so nothing breaks if you already ship one,
> but new code should use `screening`. The old name will be removed in a future
> major version.

For the full locale object and how to add other languages, see [Adapt Copy With Translations](https://docs.dynamic.xyz/docs/react/using-our-ui/design-customizations/customizing-copy-translations.md).

## Reacting in your own code

To act on a block outside the widget (clear app state, log it, or route the user elsewhere), check the reason passed to [onAuthFailure](https://docs.dynamic.xyz/docs/react/reference/events/onauthfailure.md) for a `ChainalysisError`:

```tsx theme={"system"}
import {
  ChainalysisError,
  DynamicContextProvider,
} from '@dynamic-labs/sdk-react-core';
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';

<DynamicContextProvider
  settings={{
    environmentId: 'YOUR_ENVIRONMENT_ID',
    walletConnectors: [EthereumWalletConnectors],
    events: {
      onAuthFailure: (method, reason) => {
        const error = typeof reason === 'object' ? reason.error : undefined;

        if (error instanceof ChainalysisError) {
          // recordScreeningBlock is your implementation.
          recordScreeningBlock(error.walletPublicKey);
        }
      },
    },
  }}
>
  <App />
</DynamicContextProvider>
```

`ChainalysisError` is the error class for every screening block, whichever provider produced the match. Its `walletPublicKey` holds the blocked address.

Server-side, subscribe to the [`wallet.sanctions.blocked` webhook event](https://docs.dynamic.xyz/docs/platform/console/webhooks/events) to record blocks. The webhook fires whether or not the user is still on the page.

## See also

* [Address Screening](https://docs.dynamic.xyz/docs/get-started/security/address-screening.md): what screening checks, and bringing your own provider key
* [Access Lists](https://docs.dynamic.xyz/docs/react/gating/access-lists.md): blocking or allowing specific addresses yourself


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.