Skip to main content
The personal namespace methods manage private keys and should only be used on trusted nodes. Never use these methods over untrusted connections or expose them publicly.

Overview

The personal namespace provides methods for managing accounts, signing messages, and handling wallet operations.

Account Management

personal_newAccount

Creates a new account and returns its address.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_newAccount","params":["your-password"],"id":1}' \
  http://localhost:8545
params[0]
string
required
Password to encrypt the account
result
string
The address of the newly created account
Example Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}

personal_listAccounts

Returns a list of addresses owned by the client.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_listAccounts","params":[],"id":1}' \
  http://localhost:8545
result
array
Array of account addresses
Example Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "0x1234567890123456789012345678901234567890"
  ]
}

personal_unlockAccount

Unlocks an account for a specified duration.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb","password",300],"id":1}' \
  http://localhost:8545
params[0]
string
required
Address of the account to unlock
params[1]
string
required
Password to decrypt the account
params[2]
number
Duration in seconds to keep the account unlocked (default: 300)
result
boolean
true if the account was successfully unlocked
Unlocking accounts on production nodes is a security risk. Use signed transactions instead.

personal_lockAccount

Locks an account, removing the decrypted private key from memory.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_lockAccount","params":["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"],"id":1}' \
  http://localhost:8545
params[0]
string
required
Address of the account to lock
result
boolean
true if the account was successfully locked

Key Import

personal_importRawKey

Imports a private key and creates a new account.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_importRawKey","params":["0x1234...","password"],"id":1}' \
  http://localhost:8545
params[0]
string
required
Private key (hex encoded, 64 characters without 0x prefix)
params[1]
string
required
Password to encrypt the account
result
string
Address of the imported account
Never share your private keys. Only import keys on secure, trusted nodes.

Wallet Operations

personal_listWallets

Returns a list of wallets managed by the node.
result
array
Array of wallet objects

personal_openWallet

Opens a hardware wallet.
params[0]
string
required
Wallet URL (e.g., “ledger://”, “trezor://”)
params[1]
string
Passphrase (optional, required for some hardware wallets)

personal_deriveAccount

Derives a new account from a hardware wallet.
params[0]
string
required
Wallet URL
params[1]
string
required
Derivation path (e.g., “m/44’/60’/0’/0/0”)
params[2]
boolean
Whether to pin the derived account
result
object
Derived account information

Transaction Signing

personal_sendTransaction

Sends a transaction from an unlocked account.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_sendTransaction","params":[{"from":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb","to":"0x1234567890123456789012345678901234567890","value":"0xde0b6b3a7640000"},"password"],"id":1}' \
  http://localhost:8545
params[0]
object
required
Transaction object
params[1]
string
required
Account password
result
string
Transaction hash

personal_signTransaction

Signs a transaction without sending it.
params[0]
object
required
Transaction object (same structure as personal_sendTransaction)
params[1]
string
required
Account password
result
object
Signed transaction

Message Signing

personal_sign

Signs arbitrary data with an account.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_sign","params":["0x48656c6c6f20576f726c64","0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb","password"],"id":1}' \
  http://localhost:8545
params[0]
string
required
Data to sign (hex encoded)
params[1]
string
required
Account address
params[2]
string
required
Account password
result
string
65-byte signature (hex encoded)
Example Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x1234567890abcdef..."
}
The signature includes the prefix “\x19Ethereum Signed Message:\n” + message length before hashing, following EIP-191.

personal_ecRecover

Recovers the address that signed a message.
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"personal_ecRecover","params":["0x48656c6c6f20576f726c64","0x1234567890abcdef..."],"id":1}' \
  http://localhost:8545
params[0]
string
required
Original message (hex encoded)
params[1]
string
required
Signature (65 bytes, hex encoded)
result
string
Address that signed the message

Usage Examples

JavaScript (Web3.js)

const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');

// Create new account
const newAccount = await web3.eth.personal.newAccount('password');
console.log('New account:', newAccount);

// List accounts
const accounts = await web3.eth.personal.getAccounts();
console.log('Accounts:', accounts);

// Sign message
const signature = await web3.eth.personal.sign(
  'Hello World',
  accounts[0],
  'password'
);
console.log('Signature:', signature);

// Recover signer
const signer = await web3.eth.personal.ecRecover(
  'Hello World',
  signature
);
console.log('Signer:', signer);

// Send transaction
const txHash = await web3.eth.personal.sendTransaction({
  from: accounts[0],
  to: '0x1234567890123456789012345678901234567890',
  value: web3.utils.toWei('1', 'ether')
}, 'password');
console.log('Transaction:', txHash);

Python (Web3.py)

from web3 import Web3

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

# Create new account
new_account = w3.geth.personal.new_account('password')
print(f'New account: {new_account}')

# List accounts
accounts = w3.geth.personal.list_accounts()
print(f'Accounts: {accounts}')

# Sign message
message = 'Hello World'
signature = w3.geth.personal.sign_typed_data(
    accounts[0],
    message,
    'password'
)
print(f'Signature: {signature.hex()}')

# Send transaction
tx_hash = w3.geth.personal.send_transaction({
    'from': accounts[0],
    'to': '0x1234567890123456789012345678901234567890',
    'value': w3.toWei(1, 'ether')
}, 'password')
print(f'Transaction: {tx_hash.hex()}')

Security Best Practices

Critical Security Considerations
  1. Never expose personal namespace methods over public RPC endpoints
  2. Always use strong, unique passwords for accounts
  3. Never share private keys or passwords
  4. Use hardware wallets for production environments
  5. Prefer signing transactions offline and using eth_sendRawTransaction
Instead of using personal_sendTransaction, consider:
// Better: Sign offline and send raw transaction
const signedTx = await web3.eth.accounts.signTransaction({
  to: '0x1234567890123456789012345678901234567890',
  value: web3.utils.toWei('1', 'ether'),
  gas: 21000
}, privateKey);

const receipt = await web3.eth.sendSignedTransaction(
  signedTx.rawTransaction
);

Account Storage

Accounts created with personal_newAccount are stored encrypted in the keystore directory:
~/.ethereum/keystore/  (default location)
Backup these files securely and never lose your password.

Build docs developers (and LLMs) love