Personal Signatures

Personal Signatures


Magic offers out-of-the-box Signature Request UI when the user is prompted to sign a personal or typed message for the following EVM RPC methods:

  • personal_sign
  • signTypedData_v3
  • signTypedData_v4

These methods allow dApps to verifiably prove the ownership of the user's account by getting a signature from their private key and using it to sign arbitrary and/or typed data. Additionally, it is possible to obtain a user's signature during login in a single step using login with verification feature.


  • For Dedicated Wallet, Personal Signature UI is disabled by default and can be enabled within the developer dashboard in Customization -> Widget UI. Magic also offers Sign Confirmation, a feature that secures users from front-end attacks, by prompting them to confirm the transaction in a Magic-hosted tab after clicking "Send".
  • For Universal Wallet, Personal Signature UI and Sign Confirmation are enabled by default and cannot be turned off
restricted availability

Universal wallets will soon be merged with Dedicated Wallets into a single product line. Universal apps created before February 7, 2024 will work as expected with no change. See our blog post to learn more.

#Use Cases

  • Prove verifiable ownership of a public address through signing arbitrary data provided by the dApp
  • Used in various scenarios where a user needs to sign a structured message as proof of their approval


⁠Once you have verified the correct setup of the Magic SDK and successfully authenticated the user, you can request consent to collect their information:

01import Web3 from "web3";
02import { Magic } from "magic-sdk";
03import { recoverPersonalSignature } from "@metamask/eth-sig-util";
05const magic = new Magic("YOUR_API_KEY", {
06  network: "goerli",
08const web3 = new Web3(magic.rpcProvider);
10const signAndVerify = async () => {
11  const signedMessage = await web3.eth.personal.sign(
12    "Here is a basic message!",
13    account,
14    ""
15  );
16  console.log("signedMessage:", signedMessage);
17  // recover the public address of the signer to verify
18  const recoveredAddress = recoverPersonalSignature({
19    data: message,
20    signature: signedMessage,
21  });
22  console.log(
23    recoveredAddress.toLocaleLowerCase() === account.toLocaleLowerCase()
24      ? "Signing success!"
25      : "Signing failed!"
26  );


See how to brand this experience with your own logo and colors in the customization section. ⁠