Tech, business, and useful tricks.
Vheüel Insight Network

Running a Legacy wallet.dat Extraction Script on Termux (Android)

6 min read

Learn how to prepare Termux on Android, place an old unencrypted Bitcoin wallet.dat file correctly, run a legacy private-key extraction script, and check derived Bitcoin address balances.

Vheüel

Vheüel

Author

Running a Legacy wallet.dat Extraction Script on Termux (Android)

This guide explains how to run a legacy wallet.dat extraction script on Termux using an Android device. The tutorial is intended for old, unencrypted Bitcoin wallet files where private key material may still be discoverable through binary scanning.

Important: this workflow is only for wallets that you own or are legally authorized to recover. A wallet.dat file may contain private keys. Anyone with access to valid private keys can move the funds.

This tutorial is not designed for modern descriptor wallets, encrypted wallets, hardware wallets, or seed-phrase based wallets. It is specifically focused on old legacy wallet recovery experiments.


1. What This Script Does

The script reads a local wallet.dat file as binary data, searches for private-key-like byte patterns, converts the detected data into WIF (Wallet Import Format), derives legacy Bitcoin addresses, checks balances through a public blockchain API, and writes the output into text files.

The generated files are:

  • keys.txt — extracted WIF private keys
  • balances.txt — derived addresses and detected balances

2. Scope and Limitations

This method is only useful for a narrow legacy use case. It should be treated as a recovery helper, not a guaranteed wallet recovery method.

Limitations:

  • It is intended for old unencrypted wallet files.
  • It may not work on encrypted wallet.dat files.
  • It may miss compressed-key or non-standard wallet structures.
  • It may produce false positives from random binary data.
  • It checks legacy P2PKH-style addresses.
  • It does not replace Bitcoin Core wallet recovery tools.

If the wallet is encrypted, this script will not decrypt it. If the wallet uses a newer format, this raw scanning method may not return useful results.


3. Install Termux

Install Termux from a trusted source. F-Droid is commonly preferred because the Play Store version of Termux may be outdated.

After installing Termux, update the package list:

pkg update pkg upgrade

4. Install Required Packages

Install Python and basic tools:

pkg install python git nano

Then install the Python libraries required by the script:

pip install requests base58 ecdsa

The script uses:

  • requests for API calls
  • base58 for WIF and Bitcoin address encoding
  • ecdsa for deriving public keys from private keys

5. Enable Android Storage Access

To let Termux access files from Android internal storage, run:

termux-setup-storage

After granting permission, Termux creates storage shortcuts under:

~/storage/

The shared internal storage path is usually:

~/storage/shared

6. Create a Recovery Working Directory

Create a dedicated folder for the recovery script:

mkdir -p ~/wallet-recovery cd ~/wallet-recovery

This keeps the script, wallet file, and output files in one place.


7. Place wallet.dat in the Correct Directory

If your wallet.dat file is stored in the Android Download folder, copy it into the Termux working directory:

cp ~/storage/shared/Download/wallet.dat ~/wallet-recovery/

Confirm that the file exists:

ls -lh

You should see:

wallet.dat

8. Create the Python Script

Create a file named extract.py:

nano extract.py

Paste the following script:

import re import base58 import hashlib import requests import ecdsa WALLET_FILE = "wallet.dat" KEYS_FILE = "keys.txt" BALANCES_FILE = "balances.txt" def read_wallet_file(file_path): with open(file_path, "rb") as file: return file.read() def extract_legacy_key_candidates(data): candidates = re.findall(b"\x80[\x00-\xff]{32}", data) unique_candidates = [] for candidate in candidates: if candidate not in unique_candidates: unique_candidates.append(candidate) return unique_candidates def private_key_bytes_to_wif(key_bytes): return base58.b58encode_check(key_bytes).decode() def wif_to_legacy_address(wif): decoded = base58.b58decode_check(wif) if decoded[0] != 0x80: raise ValueError("Invalid mainnet private key prefix") private_key = decoded[1:33] signing_key = ecdsa.SigningKey.from_string( private_key, curve=ecdsa.SECP256k1 ) verifying_key = signing_key.get_verifying_key() public_key = b"\x04" + verifying_key.to_string() sha256_hash = hashlib.sha256(public_key).digest() ripemd160_hash = hashlib.new("ripemd160", sha256_hash).digest() payload = b"\x00" + ripemd160_hash checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] return base58.b58encode(payload + checksum).decode() def get_balance(address): url = f"https://blockstream.info/api/address/{address}" response = requests.get(url, timeout=20) response.raise_for_status() data = response.json() funded = data["chain_stats"]["funded_txo_sum"] spent = data["chain_stats"]["spent_txo_sum"] return (funded - spent) / 100000000 def write_extracted_keys(keys): with open(KEYS_FILE, "w", encoding="utf-8") as output: if not keys: output.write("No private key candidates found.\n") return for key_bytes in keys: try: wif = private_key_bytes_to_wif(key_bytes) output.write(wif + "\n") except Exception as error: output.write(f"Failed to encode key: {error}\n") def check_balances_from_keys(): with open(KEYS_FILE, "r", encoding="utf-8") as file: wifs = [ line.strip() for line in file if line.strip() and not line.startswith("No private key") ] with open(BALANCES_FILE, "w", encoding="utf-8") as output: if not wifs: message = "No WIF keys available for balance checking." print(message) output.write(message + "\n") return print("\nBalance results:\n") for wif in wifs: try: address = wif_to_legacy_address(wif) balance = get_balance(address) line = f"{address} - {balance:.8f} BTC" print(line) output.write(line + "\n") except Exception as error: line = f"{wif[:6]}... failed: {error}" print(line) output.write(line + "\n") def main(): print("Reading wallet.dat...") data = read_wallet_file(WALLET_FILE) print("Scanning for legacy private key candidates...") keys = extract_legacy_key_candidates(data) print(f"Found {len(keys)} candidate key(s).") print(f"Writing WIF keys to {KEYS_FILE}...") write_extracted_keys(keys) print(f"Checking balances and writing results to {BALANCES_FILE}...") check_balances_from_keys() if __name__ == "__main__": main()

9. Run the Script

Make sure both files are in the same directory:

ls

You should see:

extract.py wallet.dat

Run the script:

python extract.py

10. Expected Output

If private-key candidates are found, Termux will print balance results in the terminal:

Reading wallet.dat... Scanning for legacy private key candidates... Found 2 candidate key(s). Writing WIF keys to keys.txt... Checking balances and writing results to balances.txt... Balance results: 1ExampleBitcoinAddressxxxxxxxxxxxx - 0.00000000 BTC 1AnotherBitcoinAddressxxxxxxxxxxxx - 0.01500000 BTC

The script also creates two output files:

keys.txt balances.txt

11. Understanding keys.txt

The keys.txt file contains extracted WIF keys:

5ExampleWIFPrivateKeyxxxxxxxxxxxxxxxxxxxxxxxxxxxx 5AnotherExampleWIFPrivateKeyxxxxxxxxxxxxxxxxxxxx

These keys are sensitive. Anyone with access to valid WIF private keys can control the related Bitcoin funds.


12. Understanding balances.txt

The balances.txt file contains the derived legacy Bitcoin address and its confirmed balance:

1ExampleBitcoinAddressxxxxxxxxxxxx - 0.00000000 BTC 1AnotherBitcoinAddressxxxxxxxxxxxx - 0.01500000 BTC

The balance is calculated from confirmed on-chain data returned by the Blockstream public API.


13. Important Notes About Address Format

This script derives an uncompressed legacy P2PKH-style address from each extracted private key candidate.

This is suitable for some old wallet recovery cases, but it does not cover every possible address format. If the original wallet used compressed keys or another address type, the balance may not appear even if the private key candidate is valid.


14. Security Checklist

Before and after running the script, follow these rules:

  • Work only with wallet files you own.
  • Make a backup before modifying or moving any wallet file.
  • Do not upload wallet.dat anywhere.
  • Do not share keys.txt.
  • Do not screenshot private keys.
  • Do not commit recovery files to GitHub.
  • Delete temporary sensitive files after recovery is complete.

To delete generated files after you are done:

rm -f keys.txt balances.txt

If you copied wallet.dat into Termux and no longer need it there, remove the copied file:

rm -f wallet.dat

15. Troubleshooting

No private key candidates found: the wallet may be encrypted, compressed differently, unsupported by this scanning method, or not an old unencrypted wallet.

Network error: check your internet connection or retry later. The balance lookup depends on a public blockchain API.

Zero balance: the derived legacy address may not be the address that originally received funds, or the wallet may not contain spendable coins.

Permission denied: make sure Termux has storage permission and that wallet.dat is readable from the working directory.


16. Summary

This Termux workflow is designed for old legacy wallet.dat recovery checks where raw private-key-like data may still be present in the file. The script scans the wallet file, converts detected candidates into WIF format, derives legacy Bitcoin addresses, and checks their balances.

Because this method is heuristic, it is not guaranteed to recover every wallet. It should be used carefully, offline where possible, and only with wallet files that you own or are authorized to recover.

Join Bybit