> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://v3.viem.sh/api/mcp` to find what you need.

# Verify SIWE Message \[siwe.verify]

Verifies that an [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) (Sign-In with Ethereum) formatted message was signed, supporting Smart Contract Accounts (ERC-1271/6492/8010) and Externally Owned Accounts.

Viem parses and validates the message's address, domain, nonce, scheme, and time window before calling [`verifyHash`](/docs/actions/public/verifyHash).

This action accepts every `verifyHash` option. Parsing and validation failures resolve to `false`.

## Usage

This example verifies a Sign-In with Ethereum message for an address.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const valid = await client.siwe.verify({
  message:
    'example.com wants you to sign in with your Ethereum account:\n0xA0Cf798816D4b9b9866b5330EEa46a18382f251e\n\n\nURI: https://example.com/path\nVersion: 1\nChain ID: 1\nNonce: foobarbaz12\nIssued At: 2026-01-01T00:00:00.000Z',
  signature: '0x…',
})
// @log: true
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

export const client = Client.create({
  chain: mainnet,
  transport: http(),
}).extend(publicActions())
```
:::

### Standalone Action

Call `Actions.siwe.verify` directly by passing the Client as the first argument.

:::code-group
```ts twoslash [example.ts]
import { Actions } from 'viem'
import { client } from './viem.config'

const valid = await Actions.siwe.verify(client, {
  message:
    'example.com wants you to sign in with your Ethereum account:\n0xA0Cf798816D4b9b9866b5330EEa46a18382f251e\n\n\nURI: https://example.com/path\nVersion: 1\nChain ID: 1\nNonce: foobarbaz12\nIssued At: 2026-01-01T00:00:00.000Z',
  signature: '0x…',
})
// @log: true
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = Client.create({
  chain: mainnet,
  transport: http(),
})
```
:::

## Recipes

### Validate the Sign-In Request

Pass expected request fields to bind verification to a domain, nonce, and URI scheme. Set `time` to validate the message's time window.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const message =
  'example.com wants you to sign in with your Ethereum account:\n0xA0Cf798816D4b9b9866b5330EEa46a18382f251e\n\n\nURI: https://example.com/path\nVersion: 1\nChain ID: 1\nNonce: foobarbaz12\nIssued At: 2026-01-01T00:00:00.000Z\nExpiration Time: 2026-01-01T01:00:00.000Z'

const valid = await client.siwe.verify({
  domain: 'example.com', // [!code focus]
  message,
  nonce: 'foobarbaz12', // [!code focus]
  scheme: 'https', // [!code focus]
  signature: '0x…',
  time: new Date('2026-01-01T00:30:00.000Z'), // [!code focus]
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

export const client = Client.create({
  chain: mainnet,
  transport: http(),
}).extend(publicActions())
```
:::

## Return Value

`boolean`

Whether the message is valid and was signed by the address in the message.

## Parameters

Accepts every [`verifyHash` parameter](/docs/actions/public/verifyHash#parameters) except `hash` and
`address` (the address defaults to the one in the message), plus:

### address

* **Type:** `Address`

Ethereum address to check the message's address against.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', // [!code focus]
  message,
  signature: '0x…',
})
```

### domain

* **Type:** `string`

[RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) authority to check the message's domain against.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  domain: 'example.com', // [!code focus]
  message,
  signature: '0x…',
})
```

### message

* **Type:** `string`

The full EIP-4361 formatted message that was signed.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  message, // [!code focus]
  signature: '0x…',
})
```

### nonce

* **Type:** `string`

Random string to check the message's nonce against.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  message,
  nonce: 'foobarbaz12', // [!code focus]
  signature: '0x…',
})
```

### scheme

* **Type:** `string`

[RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) URI scheme to check the message's scheme against.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  message,
  scheme: 'https', // [!code focus]
  signature: '0x…',
})
```

### time

* **Type:** `Date`
* **Default:** `new Date()`

Current time to check the message's `expirationTime` and `notBefore` fields against.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

declare const message: string
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.siwe.verify(client, {
  message,
  signature: '0x…',
  time: new Date('2026-01-01T00:00:00.000Z'), // [!code focus]
})
```

## Errors

| Error | Description |
| --- | --- |
| `RpcError.ExecutionError` | The verification request failed for a reason other than an invalid signature (invalid messages and signatures resolve to `false`). |
