⚡ Node.js₿ Crypto

Crypto Wallet Address Validation

Validate Bitcoin and Ethereum wallet addresses in Node.js. Detect address types (P2PKH, P2SH, bech32), verify EIP-55 checksums, and run parallel checks with Promise.all.

Also available in Python

1. Address types covered

ChainEndpointAddress types
Bitcoin (BTC)/v0/btc-addressP2PKH (1…), P2SH (3…), P2WPKH / P2WSH (bc1…)
Ethereum (ETH)/v0/eth-addressEIP-55 mixed-case checksum addresses

2. Validate Bitcoin address

Endpoint: GET /v0/btc-address?value=…

{
  "valid": true,
  "type": "P2WPKH"
}
type valuePrefixDescription
P2PKH1…Legacy — Pay to Public Key Hash
P2SH3…Pay to Script Hash (multisig, SegWit-wrapped)
P2WPKHbc1q… (42 chars)Native SegWit — lowest fees
P2WSHbc1q… (62 chars)Native SegWit script hash
  1. Gate on valid
  2. Use type to detect address format for fee estimation
  3. Warn users submitting legacy P2PKH addresses about higher fees

3. Validate Ethereum address

Endpoint: GET /v0/eth-address?value=…

{
  "valid": true,
  "address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
  "isChecksumValid": true
}
  1. Check valid — 40 hex chars after 0x prefix
  2. Check isChecksumValid — EIP-55 mixed-case checksum
  3. Normalise to checksummed form before storing to prevent duplicate entries
⚠️An Ethereum address is valid even without checksum casing (all lowercase passes). Always normalise to EIP-55 checksum form before storage to prevent the same address being stored twice in different cases.

4. Parallel validation with Promise.all

import { createClient } from '@isvalid-dev/sdk'

const iv = createClient({ apiKey: process.env.ISVALID_API_KEY! })

type Chain = 'BTC' | 'ETH'

interface WalletValidationResult {
  chain: Chain
  address: string
  valid: boolean
  details: Record<string, unknown>
  warnings: string[]
}

async function validateWallet(chain: Chain, address: string): Promise<WalletValidationResult> {
  const warnings: string[] = []

  if (chain === 'BTC') {
    const result = await iv.btcAddress(address)
    if (result.valid && result.type === 'P2PKH') {
      warnings.push('Legacy P2PKH address — consider migrating to bech32 (P2WPKH) for lower fees')
    }
    return { chain, address, valid: result.valid, details: result, warnings }
  } else {
    const result = await iv.ethAddress(address)
    if (result.valid && !result.isChecksumValid) {
      warnings.push('Address is valid but lacks EIP-55 checksum casing — normalise before storage')
    }
    return { chain, address, valid: result.valid, details: result, warnings }
  }
}

async function validateBoth(btcAddress: string, ethAddress: string) {
  const [btc, eth] = await Promise.all([
    validateWallet('BTC', btcAddress),
    validateWallet('ETH', ethAddress),
  ])
  return { btc, eth }
}

// Example
const result = await validateBoth(
  '1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf',
  '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed'
)
console.log('BTC valid:', result.btc.valid, '| type:', result.btc.details.type)
console.log('ETH valid:', result.eth.valid, '| checksumValid:', result.eth.details.isChecksumValid)

5. Edge cases

Wrong chain (ETH address submitted as BTC)

⚠️If a user submits an Ethereum address (0x…) to the BTC endpoint, it will return valid: false. Detect the chain from the address format before calling the API.
function detectChain(address: string): 'BTC' | 'ETH' | 'unknown' {
  if (/^0x[0-9a-fA-F]{40}$/.test(address)) return 'ETH'
  if (/^(1|3)[1-9A-HJ-NP-Za-km-z]{25,34}$/.test(address)) return 'BTC'
  if (/^bc1[a-z0-9]{6,}$/.test(address)) return 'BTC'
  return 'unknown'
}

BTC testnet addresses

ℹ️Testnet addresses (prefix m, n, or tb1) are structurally similar to mainnet but must not be used in production. The API validates mainnet addresses — reject any address that fails validation.

ETH checksum normalisation

import { getAddress } from 'ethers'

const result = await iv.ethAddress(userInput)
if (result.valid && !result.isChecksumValid) {
  // Normalise to EIP-55 checksum using ethers.js or viem
  const normalised = getAddress(userInput.toLowerCase())
  // Store normalised form
}

6. Summary checklist

Detect chain from address format before calling API
Check BTC type for fee estimation (legacy vs SegWit)
Warn users about legacy P2PKH higher fees
Validate ETH isChecksumValid for EIP-55
Normalise ETH to checksum form before storage
Run BTC + ETH checks in parallel with Promise.all
Reject testnet addresses in production flows
Return 422 with field-level error on invalid addresses

See also

Ready to integrate?

Free tier — 1,000 requests/month. No credit card required.

Get your API key →