<p>Given a list of bitcoin private keys, first you need to check the balance of the corresponding address, probably best done using a block explorer, e.g. <a href="https://www.blockchain.com/api/blockchain_api" rel="nofollow noreferrer">blockchain.info</a>:</p>

<p><strong>Single Address</strong></p>

<pre><code>https://blockchain.info/rawaddr/$bitcoin_address
Address can be base58 or hash160

Optional limit parameter to show n transactions e.g. &amp;limit=50 (Default: 50, Max: 50)
Optional offset parameter to skip the first n transactions e.g. &amp;offset=100 (Page 2 for limit 50)

{
    "hash160":"660d4ef3a743e3e696ad990364e555c271ad504b",
    "address":"1AJbsFZ64EpEfS5UAjAfcUG8pH8Jn3rn1F",
    "n_tx":17,
    "n_unredeemed":2,
    "total_received":1031350000,
    "total_sent":931250000,
    "final_balance":100100000,
    "txs":[--Array of Transactions--]
}
</code></pre>

<p>Then, you can use <a href="https://github.com/bitcoinjs/bitcoinjs-lib" rel="nofollow noreferrer"><code>bitcoinjs-lib</code></a>, for example, to <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/v4.0.1/test/integration/transactions.js#L13" rel="nofollow noreferrer">create a raw transaction</a> <strong><em>for each private key</em></strong>:</p>

<pre><code>const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
const txb = new bitcoin.TransactionBuilder()

txb.setVersion(1)
txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0) // Alice's previous transaction output, has 15000 satoshis
txb.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 12000)
// (in)15000 - (out)12000 = (fee)3000, this is the miner fee

txb.sign(0, alice)
</code></pre>

<p>For which, you will need unspent outputs to each private key's address.</p>

<p>You will also need to <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/v4.0.1/test/integration/transactions.js#L76" rel="nofollow noreferrer">broadcast the raw transaction</a>:</p>

<pre><code>// build and broadcast our RegTest network
regtestUtils.broadcast(txb.build().toHex(), done)
</code></pre>

CC BY-SA 4.0
2018-09-10T15:46:29.133Z
2018-09-10T15:46:29.133Z
JBaczuk
<p>I had a similar issue for a store I had where I was accepting bitcoin. I ended up creating a nodejs app that would take the input of just a private key and an address. It would gather all the UTXOs that belong to the private key using a third party API, and then send ALL funds to the address specified. Back then I was using bitcore-lib, but that library is now outdated, I would use bitcoin-js if I re-did it today. </p>

<p>These are the basic functions I used:</p>

<pre><code>app.post("/address", function(req,res){
    var pkey = req.body.pkey;
    var addr = req.body.addy;

    validateAddress(addr, function(isAddyValid){
        if(isAddyValid == 0){
          res.render("pages/index.ejs", {
            outMessage: "Destination address invalid"
          });  
        } else {
            validatePrivateKey(pkey, function(isPkValid){
                if(isPkValid == 0){
                    res.render("pages/index.ejs", {
                    outMessage: "Private Key invalid"
                    });
                } else {
                    convertPK(pkey, function(convertedAddy){
                        getUTXO(convertedAddy, function(result, feeAmt, totalToSend){
                            if(result == 1){
                                res.render("pages/index.ejs", {
                                    outMessage: "No UTXO"
                                });     
                            } else if(result == 2){
                                res.render("pages/index.ejs", {
                                    outMessage: "Source offline"
                                });
                            } else if(result == 3){
                                res.render("pages/index.ejs", {
                                    outMessage: "Insufficient funds to pay fee"
                                });
                            } else {
                                buildTX(result, feeAmt, totalToSend, pkey, addr, function(payloadTx){
                                    pushTX(payloadTx, function(txdone){
                                        if(txdone !== 1){
                                            res.render("pages/index.ejs", {
                                            outMessage: "TX ID: " + txdone
                                            });
                                        } else {
                                            res.render("pages/index.ejs", {
                                            outMessage: "broadcast failed try later"
                                            });
                                        }
                                    });
                                });
                            }
                        });
                    });
                }
            });//end validatePrivateKey
        }
    });//end validate address
}); //end app post

function validateAddress(output, result){
    addyValue = output.replace(/[^\w\s]/gi, '');
    if(bitcore.Address.isValid(addyValue)){
    result(1);
    } else {
    result(0);    
    };
};

//convert pk to addr
function convertPK(pkeyValue, result){
    var address = new bitcore.PrivateKey(pkeyValue).toAddress();
    result(address);
};

function validatePrivateKey(wif, result){
pkeyValue = wif.replace(/[^\w\s]/gi, '');
        if(bitcore.PrivateKey.isValid(pkeyValue)){
        //private key is valid
        result(1);
        } else {
        result(0);    
        };
};

//get outputs
function getUTXO(address, callback){
    request({
        url: "https://chain.so/api/v2/get_tx_unspent/btc/"+address,
        json: true
    }, function(error, response, body){
        if(!error &amp;&amp; response.statusCode == 200){
            if(body.data.txs.length &lt; 1){
                //no utxos
                console.log("no utxo");
                var err = 1;
                callback(err);
            }
            var status = body.status;
            var num = body.data.txs.length;
            var utxos = [];
            var totalSats = 0;  
            var txSize = 44;
                //loop through all UTXOs
                for(i=0;i &lt; num; i++){
            var convertSats = body.data.txs[i].value * 100000000;
            convertSats = parseInt(convertSats);

                    var utxo = {
                    "txId": body.data.txs[i].txid,
                    "outputIndex": body.data.txs[i].output_no,
                    "address": address,
                    "script": body.data.txs[i].script_hex,
                    "satoshis": convertSats
                    };
            utxos.push(utxo);
            totalSats = totalSats + convertSats;
            //calc tx size for fee
            txSize = txSize + 180;
                }; //end utxo loop
            getBestFee(function(bestHourFee){
                var fee = txSize * bestHourFee;
                totalSats = totalSats - fee;
                console.log(totalSats);
                console.log(fee);
                    if(totalSats &lt; 1){
                        //not enough funds to send
                        var err = 3;
                        callback(err);
                    } else {
                        callback(utxos, fee, totalSats);  
                    }
            });            
       } else {
           //err or no response from api
           console.log("no response from api");
            var error = 2;
           callback(error);
       }
    });
};

//build transaction
function buildTX(utxo, fee, total, pkeyValue, output, callback){

        var transaction = new bitcore.Transaction()
        .from(utxo)
        .to(output, total)
        .sign(pkeyValue);

        //payload to push tx
        var txjson = transaction.toString();
        var pload = {
            "tx": txjson
        };
        callback(pload);  
};


//push transaction
function pushTX(pload, callback){
    request({
    url: "https://api.blockcypher.com/v1/btc/main/txs/push",
    method: "POST",
    json: true,
    headers: {"content-type": "application/json"},
    body: pload
    }, function(err, response, body){
            if(err){ 
         //no response or error POST to chainso
             callback(1);    
        } else {
                console.log(JSON.stringify(body));
                completeTxId = body.tx.hash;
                console.log("done");
                callback(completeTxId);
            };                
    });
};

function getBestFee(bestFee){
  var findfee = "https://bitcoinfees.21.co/api/v1/fees/recommended";
    request({
        url: findfee,
        json: true
    }, function(error, response, body){
        if(!body.hourFee){
            //no response from api use 150 sats per byte
            var fee = 150;
            bestFee(fee);
        }
        if(body.hourFee){
            var fee = body.hourFee;
            fee = fee * 0.5;
            fee = Math.ceil(fee);
            bestFee(fee);
        }
    });  
}
</code></pre>

<p>If you want to see the entire project here's the repo, it's a simple nodejs express app with a form submission POST option and a GET endpoint <code>/sweep</code> option. Be aware the way I wrote it, it will only work with legacy P2PKH addresses (addresses that start with a 1), no segwit. </p>

<p><a href="https://github.com/coinables/sweepkey" rel="nofollow noreferrer">https://github.com/coinables/sweepkey</a></p>

CC BY-SA 4.0
2018-09-14T09:06:01.387Z
Sending private key through API post request body is not a good approach.
Mohammed niyas
CC BY-SA 4.0
2020-01-07T07:09:26.067Z
you're using https://api.blockcypher.com/v1/btc/main/txs/push to post transactions.  what is the testnet version of this? I tried `test` and `testnet` but both fail
ekkis
CC BY-SA 4.0
2018-09-11T02:47:36.523Z
2018-09-11T02:56:34.007Z
2018-09-11T02:56:34.007Z
m1xolyd1an
<p>I have a list of bitcoin addresses and private keys, I need to write an automation script which checks for the balance in each address and transfer the balance funds to another bitcoin address. My question is how I perform the fund transfer with address and privateKey using nodejs</p>

<p>Thanks in Advance</p>

CC BY-SA 4.0
2018-09-10T13:38:03.707Z
i.e. "How do I steal bitcoin from accounts I've hacked..."
JBaczuk
CC BY-SA 4.0
2018-09-10T15:14:01.410Z
No, it's not stealing bitcoins. I have the list of accounts and privateKeys that I have generated. I am using these accounts for receiving funds. For privacy reasons, I keep on switching the incoming address and monitor all the address and if any funds deposited on these address I move those funds to my hot wallet address.
Mohammed niyas
CC BY-SA 4.0
2018-09-10T15:38:54.920Z
Oh, ok :). Your use case is exactly why HD wallets (BIP32) were introduced. You can generate many addresses from a single private key and not have to store a list of private keys.
JBaczuk
<transactions><address>
How to initiate a transaction with address and privateKey using nodejs
Mohammed niyas
# How to initiate a transaction with address and privateKey using nodejs

(Asked by: username_0 on 2018-09-10)

I have a list of bitcoin addresses and private keys, I need to write an automation script which checks for the balance in each address and transfer the balance funds to another bitcoin address. My question is how I perform the fund transfer with address and privateKey using nodejs

Thanks in Advance

**Tags:** transactions, address

> **Comments:**
> **username_1**: i.e. "How do I steal bitcoin from accounts I've hacked..."  
> **username_0**: No, it's not stealing bitcoins. I have the list of accounts and privateKeys that I have generated. I am using these accounts for receiving funds. For privacy reasons, I keep on switching the incoming address and monitor all the address and if any funds deposited on these address I move those funds to my hot wallet address.  
> **username_1**: Oh, ok :). Your use case is exactly why HD wallets (BIP32) were introduced. You can generate many addresses from a single private key and not have to store a list of private keys.  

---

## 2 answers

### Answer by username_1 on 2018-09-10. Score: 0 | Accepted answer

Given a list of bitcoin private keys, first you need to check the balance of the corresponding address, probably best done using a block explorer, e.g. [blockchain.info](https://www.blockchain.com/api/blockchain_api):

**Single Address**

```
https://blockchain.info/rawaddr/$bitcoin_address
Address can be base58 or hash160

Optional limit parameter to show n transactions e.g. &limit=50 (Default: 50, Max: 50)
Optional offset parameter to skip the first n transactions e.g. &offset=100 (Page 2 for limit 50)

{
    "hash160":"660d4ef3a743e3e696ad990364e555c271ad504b",
    "address":"1AJbsFZ64EpEfS5UAjAfcUG8pH8Jn3rn1F",
    "n_tx":17,
    "n_unredeemed":2,
    "total_received":1031350000,
    "total_sent":931250000,
    "final_balance":100100000,
    "txs":[--Array of Transactions--]
}

```

Then, you can use [`bitcoinjs-lib`](https://github.com/bitcoinjs/bitcoinjs-lib), for example, to [create a raw transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/v4.0.1/test/integration/transactions.js#L13) ***for each private key***:

```
const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
const txb = new bitcoin.TransactionBuilder()

txb.setVersion(1)
txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0) // Alice's previous transaction output, has 15000 satoshis
txb.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 12000)
// (in)15000 - (out)12000 = (fee)3000, this is the miner fee

txb.sign(0, alice)

```

For which, you will need unspent outputs to each private key's address.

You will also need to [broadcast the raw transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/v4.0.1/test/integration/transactions.js#L76):

```
// build and broadcast our RegTest network
regtestUtils.broadcast(txb.build().toHex(), done)

```


---

### Answer by username_2 on 2018-09-11. Score: 0

I had a similar issue for a store I had where I was accepting bitcoin. I ended up creating a nodejs app that would take the input of just a private key and an address. It would gather all the UTXOs that belong to the private key using a third party API, and then send ALL funds to the address specified. Back then I was using bitcore-lib, but that library is now outdated, I would use bitcoin-js if I re-did it today.

These are the basic functions I used:

```
app.post("/address", function(req,res){
    var pkey = req.body.pkey;
    var addr = req.body.addy;

    validateAddress(addr, function(isAddyValid){
        if(isAddyValid == 0){
          res.render("pages/index.ejs", {
            outMessage: "Destination address invalid"
          });  
        } else {
            validatePrivateKey(pkey, function(isPkValid){
                if(isPkValid == 0){
                    res.render("pages/index.ejs", {
                    outMessage: "Private Key invalid"
                    });
                } else {
                    convertPK(pkey, function(convertedAddy){
                        getUTXO(convertedAddy, function(result, feeAmt, totalToSend){
                            if(result == 1){
                                res.render("pages/index.ejs", {
                                    outMessage: "No UTXO"
                                });     
                            } else if(result == 2){
                                res.render("pages/index.ejs", {
                                    outMessage: "Source offline"
                                });
                            } else if(result == 3){
                                res.render("pages/index.ejs", {
                                    outMessage: "Insufficient funds to pay fee"
                                });
                            } else {
                                buildTX(result, feeAmt, totalToSend, pkey, addr, function(payloadTx){
                                    pushTX(payloadTx, function(txdone){
                                        if(txdone !== 1){
                                            res.render("pages/index.ejs", {
                                            outMessage: "TX ID: " + txdone
                                            });
                                        } else {
                                            res.render("pages/index.ejs", {
                                            outMessage: "broadcast failed try later"
                                            });
                                        }
                                    });
                                });
                            }
                        });
                    });
                }
            });//end validatePrivateKey
        }
    });//end validate address
}); //end app post

function validateAddress(output, result){
    addyValue = output.replace(/[^\w\s]/gi, '');
    if(bitcore.Address.isValid(addyValue)){
    result(1);
    } else {
    result(0);    
    };
};

//convert pk to addr
function convertPK(pkeyValue, result){
    var address = new bitcore.PrivateKey(pkeyValue).toAddress();
    result(address);
};

function validatePrivateKey(wif, result){
pkeyValue = wif.replace(/[^\w\s]/gi, '');
        if(bitcore.PrivateKey.isValid(pkeyValue)){
        //private key is valid
        result(1);
        } else {
        result(0);    
        };
};

//get outputs
function getUTXO(address, callback){
    request({
        url: "https://chain.so/api/v2/get_tx_unspent/btc/"+address,
        json: true
    }, function(error, response, body){
        if(!error && response.statusCode == 200){
            if(body.data.txs.length < 1){
                //no utxos
                console.log("no utxo");
                var err = 1;
                callback(err);
            }
            var status = body.status;
            var num = body.data.txs.length;
            var utxos = [];
            var totalSats = 0;  
            var txSize = 44;
                //loop through all UTXOs
                for(i=0;i < num; i++){
            var convertSats = body.data.txs[i].value * 100000000;
            convertSats = parseInt(convertSats);

                    var utxo = {
                    "txId": body.data.txs[i].txid,
                    "outputIndex": body.data.txs[i].output_no,
                    "address": address,
                    "script": body.data.txs[i].script_hex,
                    "satoshis": convertSats
                    };
            utxos.push(utxo);
            totalSats = totalSats + convertSats;
            //calc tx size for fee
            txSize = txSize + 180;
                }; //end utxo loop
            getBestFee(function(bestHourFee){
                var fee = txSize * bestHourFee;
                totalSats = totalSats - fee;
                console.log(totalSats);
                console.log(fee);
                    if(totalSats < 1){
                        //not enough funds to send
                        var err = 3;
                        callback(err);
                    } else {
                        callback(utxos, fee, totalSats);  
                    }
            });            
       } else {
           //err or no response from api
           console.log("no response from api");
            var error = 2;
           callback(error);
       }
    });
};

//build transaction
function buildTX(utxo, fee, total, pkeyValue, output, callback){

        var transaction = new bitcore.Transaction()
        .from(utxo)
        .to(output, total)
        .sign(pkeyValue);

        //payload to push tx
        var txjson = transaction.toString();
        var pload = {
            "tx": txjson
        };
        callback(pload);  
};

//push transaction
function pushTX(pload, callback){
    request({
    url: "https://api.blockcypher.com/v1/btc/main/txs/push",
    method: "POST",
    json: true,
    headers: {"content-type": "application/json"},
    body: pload
    }, function(err, response, body){
            if(err){ 
         //no response or error POST to chainso
             callback(1);    
        } else {
                console.log(JSON.stringify(body));
                completeTxId = body.tx.hash;
                console.log("done");
                callback(completeTxId);
            };                
    });
};

function getBestFee(bestFee){
  var findfee = "https://bitcoinfees.21.co/api/v1/fees/recommended";
    request({
        url: findfee,
        json: true
    }, function(error, response, body){
        if(!body.hourFee){
            //no response from api use 150 sats per byte
            var fee = 150;
            bestFee(fee);
        }
        if(body.hourFee){
            var fee = body.hourFee;
            fee = fee * 0.5;
            fee = Math.ceil(fee);
            bestFee(fee);
        }
    });  
}

```

If you want to see the entire project here's the repo, it's a simple nodejs express app with a form submission POST option and a GET endpoint `/sweep` option. Be aware the way I wrote it, it will only work with legacy P2PKH addresses (addresses that start with a 1), no segwit.

<https://github.com/coinables/sweepkey>

> **Comments:**
> **username_0**: Sending private key through API post request body is not a good approach.  
> **username_3**: you're using https://api.blockcypher.com/v1/btc/main/txs/push to post transactions.  what is the testnet version of this? I tried `test` and `testnet` but both fail  

---

