Independent review. This site is not the official website and is not affiliated with, endorsed by, or operated by the wallet vendor reviewed here. Never enter your seed phrase or private keys on any third-party site.

MetaMask Snaps & Developer Integration — Detecting & Using Snaps

Try Tangem secure wallet →

Why check if a snap is connected?

If your dApp relies on a MetaMask snap (for example a custom signing flow, an on-chain helper, or a utility exposed by the snap), you need a reliable way to detect whether the snap is available before calling into it. Otherwise your app will throw errors or create bad UX for users.

Want to confirm snap access before calling methods? Good. Short checks prevent failed transactions and unexpected permission prompts. In my experience it's better to check first, then request install or show a clear guide to the user.

And yes, you should treat snaps like another permission layer: installed does not always mean allowed for the current origin.

How MetaMask exposes snaps to dApps (quick overview)

MetaMask exposes snaps via the injected provider (window.ethereum) using JSON-RPC-style requests (EIP-1193 provider pattern). The most commonly used method for discovery is wallet_getSnaps, which returns information about snaps the extension currently manages. That output is what your dApp can read to determine presence and some metadata.

Try Tangem secure wallet →

What that output contains depends on MetaMask's version and the snap's manifest. Typically you'll see IDs, versions, and permission-related fields (example below). If those fields are missing, fall back to a safe call (explained later).

For general dApp connection patterns see the developer workflow guide: [/developer-workflow]. For basic MetaMask connection and dApp UX patterns, this page helps: [/connect-metamask-to-dapps].

Quick detection: wallet_getSnaps (plain JavaScript)

This is the simplest reproducible test. Open your dApp page and run (or include) this code:

async function isSnapInstalled(snapId) {
  if (!window.ethereum || !window.ethereum.request) return false;
  try {
    const snaps = await window.ethereum.request({ method: 'wallet_getSnaps' });
    return Boolean(snaps && snaps[snapId]);
  } catch (err) {
    console.error('wallet_getSnaps error', err);
    return false;
  }
}

// Usage
const SNAP_ID = 'npm:example-snap';
isSnapInstalled(SNAP_ID).then(installed => console.log('installed?', installed));

Sample console output (example only):

{
  "npm:example-snap": {
    "id": "npm:example-snap",
    "version": "0.1.0",
    "enabled": true,
    "manifest": { /* ... */ }
  }
}

This pattern answers the primary question: determine if metamask snap is connected. If the key exists in the returned object, the snap is present in the extension.

React example: determine is metamask snap is connected in react

A minimal hook-based pattern works well in React apps. This answers the specific search intent: determine is metamask snap is connected in react.

import { useEffect, useState } from 'react';

export function useSnapStatus(snapId, pollInterval = 15000) {
  const [isInstalled, setIsInstalled] = useState(false);
  const [meta, setMeta] = useState(null);

  useEffect(() => {
    let mounted = true;

    async function check() {
      if (!window.ethereum || !window.ethereum.request) {
        setIsInstalled(false);
        setMeta(null);
        return;
      }

      try {
        const snaps = await window.ethereum.request({ method: 'wallet_getSnaps' });
        const info = snaps?.[snapId] ?? null;
        if (!mounted) return;
        setIsInstalled(Boolean(info));
        setMeta(info);
      } catch (err) {
        console.error('check snaps failed', err);
        if (mounted) setIsInstalled(false);
      }
    }

    check();
    const id = setInterval(check, pollInterval);
    return () => {
      mounted = false;
      clearInterval(id);
    };
  }, [snapId, pollInterval]);

  return { isInstalled, meta };
}

Use that hook in your components to show an install button or a troubleshooting message (link users to your step-by-step install flow). But avoid repeatedly prompting — prompt only on user action.

Safe ping & deeper checks (confirm functionality)

Detecting presence is one thing. Confirming that the snap will actually respond to your method is another. Two safe checks I use:

  • Read-only ping: have your snap expose a no-state-change endpoint (for example, a simple ping or version RPC). Call it and handle failure gracefully.
  • Permissions check: inspect returned metadata from wallet_getSnaps for flags like enabled or initialPermissions (if available).

Example pseudo-call (pattern — snap APIs may evolve):

try {
  const result = await window.ethereum.request({
    method: 'wallet_invokeSnap',
    params: { snapId: SNAP_ID, request: { method: 'ping', params: [] } }
  });
  // success -> snap responds
} catch (err) {
  // failed -> not available or not allowed
}

Note: API names can change as the Snaps system evolves. If you rely on a specific method name, validate against the current MetaMask Snaps developer docs.

Developer testing: how I tested this and how you can replicate

What I did (replicable steps):

  1. Run a local dApp on http://localhost:3000 (create-react-app or static server).
  2. Open Chrome with the MetaMask extension installed (desktop). Connect an account to the dApp (standard connect flow — see [/connect-metamask-to-dapps]).
  3. In the dApp code, include the wallet_getSnaps call above. Open DevTools and observe the returned object.
  4. Install or enable your snap in MetaMask (trigger from the UI or via a controlled request), then rerun wallet_getSnaps to observe the change.

I used a local development snap during testing and a Hardhat/Ganache node to avoid spending real funds (see [/local-development-ganache-geth]). The pattern above is reproducible with any snap ID (npm: or local: prefixes are common).

MetaMask snaps security: permissions, revocation, and best practices

Snaps extend a software wallet's surface area. That adds capability — and risk. Here are practical, tested precautions I recommend.

  • Review permissions before install. Snaps typically declare permissions in their manifest. Ask yourself: does this snap need the permission? If not, don't install.
  • Use read-only pings first. Confirm the snap responds to a harmless method before calling state-changing functions.
  • Revoke or remove snaps you no longer trust. Inspect MetaMask settings and remove the snap (and revoke token approvals as needed) — see [/token-approvals-and-revoke].
  • Test on a local or testnet environment before using a snap with real funds (see [/local-development-ganache-geth]).

But remember: a hot wallet (software wallet) trades convenience for exposure. If your use case requires high-value custody, pair snaps with a hardware wallet workflow or avoid granting broad permissions.

For broader security practices and troubleshooting, check these pages: [/security-and-safety], [/troubleshooting].

FAQ: common questions about snaps & connection status

Q: Is it safe to rely only on wallet_getSnaps?
A: It's a good first check. But also do a safe ping or permission check before performing sensitive operations.

Q: What if the snap is installed but my call still fails?
A: The snap might not have the permission for your origin, the API might differ between versions, or the snap could be disabled. Re-check the snap metadata and prompt the user to re-enable if needed.

Q: Can I detect snaps with WalletConnect or mobile flows?
A: Support varies. Test on the platform you target (mobile support differs). For mobile dApp flows, consult [/walletconnect-and-mobile-dapps] and test directly.

Q: How do I revoke a snap or clean up after experiments?
A: Remove the snap via the MetaMask UI and revoke any token approvals as needed (see [/token-approvals-and-revoke]).

Summary and next steps

How to determine if metamask snap is connected? Start with wallet_getSnaps, then confirm with a safe, read-only call. If you're building in React, use the hook pattern shown above for clean UI signals. What I've found in daily use is that a quick presence check plus a ping step prevents most runtime errors.

If you develop snaps, keep a local test harness and include a read-only health endpoint. And if you're integrating snaps into a DeFi flow, pair checks with user-facing instructions so they understand permissions before they trade or stake.

Try the code snippets in a local dApp, repeat the wallet_getSnaps query in your console, and then build a small ping method in your snap for robust verification. For related guides on connecting MetaMask, permission handling, and developer workflow, see: [/connect-metamask-to-dapps], [/developer-workflow], [/token-approvals-and-revoke].

Ready for the next step? Add a health-check to your dApp and handle the install flow gracefully — that will reduce support tickets and protect users.

Console output showing wallet_getSnaps (placeholder image)

Try Tangem secure wallet →