Open-source, non-custodial Monero web wallet. Your keys never leave your browser.
Live at monero-web.com
A browser-based Monero wallet that runs entirely client-side. No downloads, no extensions, no app stores. Enter your seed phrase or private key and access your wallet from any device.
- Create new wallets — generate a 25-word seed phrase using browser cryptographic RNG
- Restore from seed — supports 25-word standard and 13-word MyMonero legacy seeds
- Import from spend key — paste your 64-character hex private spend key
- 13 languages — English, Chinese (simplified), Dutch, Esperanto, French, German, Italian, Japanese, Lojban, Portuguese, Russian, Spanish, English (old)
- Live network data — blockchain height, fee estimates, tx pool size via remote node connection
- Receive with QR — generate QR codes for your Monero address
- Non-custodial — private keys are derived and used in the browser only, never transmitted
- Zero dependencies — pure JavaScript crypto engine, no npm, no build tools
Browser (client-side)
├── keccak256.js — Original Keccak-256 (0x01 padding, NOT SHA-3)
├── monero-ed25519.js — Ed25519 scalar mult, sc_reduce32, CryptoNote base58
├── monero-wordlist.js — Mnemonic handler with CRC32 checksum verification
├── monero-keys.js — Key derivation: seed → spend key → view key → address
├── monero-rpc.js — JSON-RPC client via serverless proxy
└── monero-wordlists — All 13 language wordlists (1626 words each)
Cloudflare Pages (serverless)
├── functions/api/proxy.js — Smart RPC proxy (prefers own node when synced, falls back to public nodes)
└── functions/_middleware.js — Cache-control headers
Dedicated Server (Hetzner, self-hosted)
├── monerod — Pruned Monero node (synced, RPC on localhost:18081)
└── monero-lws — Light-wallet server for balance scanning (REST on localhost:8443)
Seed Phrase (25 words)
↓ decode via wordlist
Private Spend Key (32 bytes)
↓ sc_reduce32
Private Spend Key (valid scalar)
↓ Keccak-256 → sc_reduce32
Private View Key
↓ ed25519 base point multiplication
Public Spend Key + Public View Key
↓ network byte + pub keys + Keccak checksum → base58
Monero Address (95 characters, starts with 4)
MyMonero used a different derivation path than standard Monero:
- 12 data words + 1 checksum → 16 bytes
- 16 bytes → Keccak-256 → sc_reduce32 → Private Spend Key
- 16 bytes → Keccak-256 → Keccak-256 → sc_reduce32 → Private View Key
This wallet is one of the few that still supports MyMonero 13-word legacy seeds after MyMonero shut down in January 2026.
- Client-side only — all cryptographic operations run in your browser
- No key storage — keys exist only in sessionStorage, cleared when you close the tab
- No tracking — no analytics, no cookies, no telemetry
- Open source — audit the code yourself
- Proxy is key-blind — the Cloudflare Pages proxy forwards RPC requests to Monero nodes but never sees your private keys. The light-wallet server (monero-lws) sees your view key for scanning but never sees your spend key
The serverless proxy forwards JSON-RPC calls to Monero remote nodes. It can see:
- That someone is making RPC requests (blockchain height, fee estimates)
- Transaction broadcasts (the signed tx hex, not the spend key)
It cannot see your private keys, seed phrase, or wallet balance.
Clone this repo and deploy to any static hosting:
git clone https://github.com/Medtabka/monero-web.git
cd monero-web
# Deploy to Cloudflare Pages, Vercel, or any static host
# For the RPC proxy, you need Cloudflare Functions or your own backend
# For balance scanning, run monerod + monero-lws on a VPSOr run locally:
python3 -m http.server 8000
# Open http://localhost:8000/verify.html
# Note: RPC proxy won't work locally, only key derivationThe crypto engine has Node-runnable tests for the new code paths:
node tests/test-new-paths.jsThis exercises BIP-39, polyseed (canonical + 4-char-prefix), subaddress generation, network selection (mainnet / stagenet / testnet), and the WalletVault encrypted session-storage round-trip.
This wallet is designed to keep your spend key out of any system you don't control. Below is what it does and does not protect against — please read this before trusting it with significant funds.
Invariant enforced by CI: every byte the browser executes (HTML, JS, CSS,
fonts, images, the QR encoder library) is served from monero-web.com. The
build pipeline fails if any HTML file references an external CDN URL. There
is no <script src="https://cdn.example.com/..."> anywhere in the project,
ever, by construction. This means there is no third-party JavaScript supply
chain to compromise.
What monero-web protects against:
- A compromised or malicious server. All key derivation, all signing, and all address generation happen inside your browser tab. The Cloudflare host that serves the static files never sees your seed, keys, or balance. Even the RPC proxy is key-blind: it sees blockchain queries, not wallet contents.
- A compromised npm dependency. There are no dependencies. The crypto engine
is hand-written JavaScript checked into this repo. There is no
package.json, no transitive dep tree, and no build pipeline that could swap in malicious code. - A compromised "remote node" you connect to. RPC traffic goes through the proxy by default; you can set a custom node from the dashboard if you prefer. In neither case does the node ever receive your private keys.
- Memory snapshots while idle. With a session password set, the keys are
AES-GCM encrypted in
sessionStorage. After 10 minutes of inactivity the page reloads, dropping the in-memory copy and forcing re-unlock. - Tab close / browser restart. Keys live in
sessionStorage, notlocalStorage. Closing the tab wipes them.
What monero-web does NOT protect against:
- A compromised browser extension. Extensions with broad permissions can read page content, intercept clipboard reads, and exfiltrate keys. Use a clean browser profile (or a separate browser entirely) when handling significant funds.
- A compromised operating system. Keystroke loggers, screen recorders, rootkits, and process-memory readers can all defeat any browser-based wallet.
- Hostile DNS / a TLS MITM with a rogue CA. If an attacker can serve you
modified JavaScript under the
monero-web.comorigin, they can ship a wallet that emails them your seed. Mitigations: pin a known-good commit, run from the local repo (python3 -m http.server), or self-host. - XSS. A successful injection on the origin can read everything in the page, including your in-memory keys. The site sets a strict CSP and ships no user-generated content, but no defense is perfect.
- You typing your seed into a fake clone. Always check the URL.
monero-web.comis the only canonical host. - Phishing for your session password. The session password protects the
encrypted-at-rest blob in
sessionStorage, not the in-memory keys. While the dashboard is unlocked the keys are decrypted in JS memory. - Send-side key exposure. Sending Monero requires the spend key to be in memory at signing time. The send flow uses the mymonero-core WASM module to sign transactions client-side — the spend key stays in the browser and is never sent to the server — but it is still present in JS memory while the dashboard tab is unlocked.
If your threat model includes nation-state actors or you're moving funds you can't afford to lose, use Monero CLI on an air-gapped machine.
- Key derivation engine (Keccak-256, Ed25519, sc_reduce32)
- 12-word BIP-39 support (PBKDF2-SHA512 + SLIP-0010 ed25519)
- 13-word MyMonero seed support
- 16-word Polyseed support (GF(2¹¹) checksum + PBKDF2-SHA256 KDF)
- 25-word standard Monero seed (all 13 wordlist languages)
- Subaddress generation (
8…mainnet) - Watch-only import (address + view key)
- Network selector (mainnet / stagenet / testnet)
- Encrypted session storage (AES-GCM via PBKDF2-SHA256)
- Idle auto-lock with re-unlock prompt
- Custom node URL (bypass the proxy)
- Wallet JSON export
- Receive screen with client-side QR code
- Live network data via remote node
- Balance scanning via self-hosted monero-lws (light-wallet server)
- Send XMR with client-side WASM transaction signing (mymonero-core-js)
- Transaction history via LWS
- Address book / labeled subaddresses with localStorage persistence
- QR code scanner for
monero:URIs (camera-based, vendored jsQR) - Strict CSP without
'unsafe-inline'for scripts - DNSSEC end-to-end (Cloudflare + Porkbun)
- Self-hosted monerod (pruned) + monero-lws on Hetzner CAX21
- Smart RPC proxy (auto-fails over to public nodes when own node is down)
- Swap integration (ChangeNow / Majestic Bank)
- PWA support (install on home screen)
MyMonero shut down in January 2026, leaving users of its 13-word seed format without a web wallet. Cake Wallet doesn't accept 13-word MyMonero seeds. This project fills that gap and supports all Monero seed formats in one place.
PRs welcome. The crypto code is intentionally kept simple and dependency-free for auditability.
MIT
monero-web is free, MIT-licensed, and has no token, no premium tier, and no ads. If you find it useful, XMR donations are very appreciated and go directly to keeping the project alive:
47RzzwG62wBc5zDLm3M3xGUJAw7AY6vnW4hSHqo1jyJF1UsHCv56pPLgw4LAGwgfEe5RrR9SwaatBXtr77ZMW7sgTVZeRCz
