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):
- Run a local dApp on http://localhost:3000 (create-react-app or static server).
- Open Chrome with the MetaMask extension installed (desktop). Connect an account to the dApp (standard connect flow — see [/connect-metamask-to-dapps]).
- In the dApp code, include the wallet_getSnaps call above. Open DevTools and observe the returned object.
- 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.
