> For the complete documentation index, see [llms.txt](/llms.txt).

# Use headless mode

By default, MetaMask Connect renders its own QR code modal when connecting to MetaMask Mobile via MetaMask Wallet Protocol (MWP). Headless mode suppresses this built-in modal so you can render your own connection UI.

Use headless mode when you want to:

- Display a custom-styled QR code that matches your dapp's design.
- Show the connection URI in a different format (for example, a deeplink button instead of a QR code).
- Integrate the connection flow into an existing modal or onboarding wizard.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

Follow Step 1 of the [quickstart](/metamask-connect/evm/quickstart/javascript/) to install the EVM client.

## Steps[​](#steps "Direct link to Steps")

### 1. Initialize the client with headless mode[​](#1-initialize-the-client-with-headless-mode "Direct link to 1. Initialize the client with headless mode")

Initialize an EVM client using [createEVMClient](/metamask-connect/evm/reference/methods/#createevmclient), and set `ui.headless` to `true`:

```
import { createEVMClient, getInfuraRpcUrls } from '@metamask/connect-evm'

const evmClient = await createEVMClient({
  dapp: {
    name: 'My Dapp',
    url: window.location.href,
  },
  api: {
    supportedNetworks: {
      ...getInfuraRpcUrls({ infuraApiKey: '<YOUR_INFURA_API_KEY>' }),
    },
  },
  ui: { headless: true },
})

```

### 2. Register a `display_uri` listener before connecting[​](#2-register-a-display%5Furi-listener-before-connecting "Direct link to 2-register-a-display_uri-listener-before-connecting")

The `display_uri` event fires on the EIP-1193 [provider](/metamask-connect/evm/reference/provider-api/) during the connecting phase with a one-time-use pairing URI. You **must** register the listener before calling `connect`, or you may miss the event:

```
const provider = evmClient.getProvider()

provider.on('display_uri', uri => {
  showCustomQrModal(uri)
})

```

As an alternative to `provider.on`, you can pass a `displayUri` callback when initializing the client via [eventHandlers](/metamask-connect/evm/reference/methods/#createevmclient) (see the [migration guide](/metamask-connect/evm/guides/migrate-from-sdk/#6-update-event-handling)).

### 3. Connect and handle the result[​](#3-connect-and-handle-the-result "Direct link to 3. Connect and handle the result")

Call [connect](/metamask-connect/evm/reference/methods/#connect) to connect to MetaMask, and handle the result:

```
try {
  await evmClient.connect({ chainIds: ['0x1'] })
  hideCustomQrModal()
} catch (err) {
  hideCustomQrModal()
  if (err.code === 4001) {
    // User rejected — show retry UI
  } else {
    console.error('Connection failed:', err)
  }
}

```

## Important considerations[​](#important-considerations "Direct link to Important considerations")

### URI is one-time-use[​](#uri-is-one-time-use "Direct link to URI is one-time-use")

The pairing URI delivered by `display_uri` is a one-time-use token. Once used or expired, it cannot be reused. If the connection fails, call `connect` again to generate a fresh URI.

### `display_uri` only fires during connecting[​](#display%5Furi-only-fires-during-connecting "Direct link to display_uri-only-fires-during-connecting")

The event fires only while the client status is `'connecting'`. After the connection resolves (success or error), `display_uri` stops firing.

### Extension connections skip QR[​](#extension-connections-skip-qr "Direct link to Extension connections skip QR")

When the MetaMask browser extension is installed and `ui.preferExtension` is `true` (the default), the SDK connects directly through the extension. No `display_uri` event fires because no QR code is needed.

To display the QR connection option even when the extension is available, set `ui.preferExtension` to `false`:

```
const evmClient = await createEVMClient({
  dapp: { name: 'My Dapp', url: window.location.href },
  api: {
    supportedNetworks: {
      ...getInfuraRpcUrls({ infuraApiKey: '<YOUR_INFURA_API_KEY>' }),
    },
  },
  ui: {
    headless: true,
    preferExtension: false,
  },
})

```

### Monitor connection status[​](#monitor-connection-status "Direct link to Monitor connection status")

The EVM client exposes a [status](/metamask-connect/evm/reference/methods/#properties) property (`'loaded' | 'pending' | 'connecting' | 'connected' | 'disconnected'`) you can read when updating UI.

## Next steps[​](#next-steps "Direct link to Next steps")

- [Send transactions](/metamask-connect/evm/guides/send-transactions/) in your JavaScript or Wagmi dapp.
- [Sign data](/metamask-connect/evm/guides/sign-data/) with the connected session.
- See the [EVM methods reference](/metamask-connect/evm/reference/methods/) for the full API.
