<p>I needed a trustworthy history of mining difficulty changes and also landed on the blockchain.info chart that clearly has incorrect (averaged) data. So I wrote this script that uses the Esplora API to search for difficulty changes. The logic could be easily ported to run against your own Esplora instance or your own Bitcoin node's RPC API.</p>
<p>Script is here: <a href="https://github.com/jlopp/bitcoin-utils/blob/master/generateDifficultyHistoryCSV.php" rel="nofollow noreferrer">https://github.com/jlopp/bitcoin-utils/blob/master/generateDifficultyHistoryCSV.php</a></p>
<pre><code>&lt;?php

// This script uses the blockstream explorer API
// It iterates through every block that was minted after a difficulty retarget height
// and if the difficulty changed compared to the previous epoch, will print it in CSV format

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

$currentBlockHeight = 38304; // one epoch before the first difficulty change (speed up the script by reducing API calls)
$currentBlockHash = NULL;
$currentDifficulty = 1;

// determine where to stop looking for new difficulty epochs
curl_setopt($ch, CURLOPT_URL, &quot;https://blockstream.info/api/blocks/tip/height&quot;);
$chainTipHeight = curl_exec($ch);
$maxBlockHeight = $chainTipHeight - ($chainTipHeight % 2016) - 2016;

echo &quot;\nBlock Height,Date,Difficulty\n&quot;;
echo &quot;0,2009-01-03,1\n&quot;;

while ($currentBlockHeight &lt; $maxBlockHeight) {  // there are more difficulty retargets
    $currentBlockHeight += 2016;
    curl_setopt($ch, CURLOPT_URL, &quot;https://blockstream.info/api/block-height/$currentBlockHeight&quot;);
    $currentBlockHash = curl_exec($ch);

    curl_setopt($ch, CURLOPT_URL, &quot;https://blockstream.info/api/block/$currentBlockHash&quot;);
    $block = json_decode(curl_exec($ch));
    if ($block-&gt;difficulty != $currentDifficulty) {
        echo $block-&gt;height . &quot;,&quot; . date(&quot;Y-m-d&quot;, $block-&gt;timestamp) . &quot;,&quot; . $block-&gt;difficulty . &quot;\n&quot;;
    }

}
</code></pre>

CC BY-SA 4.0
2022-09-14T14:12:01.813Z
As it's only 34 lines, you could inline it here (with a note of where the latest version can be found) to avoid future issues with link-rot/404
RedGrittyBrick
CC BY-SA 4.0
2022-09-13T15:08:17.673Z
2022-09-15T15:03:41.850Z
2022-09-15T15:03:41.850Z
Jameson Lopp
<p>The data is also stored on the block chain.  Query every 2016 blocks to see the difficulty at that time.  Here are some samples, can see block 131040 was a re-target.</p>

<pre><code># bitcoin-cli getblockhash 4032 | xargs bitcoin-cli getblock
{
    "hash" : "00000000ca4b69045a03d7b20624def97a5366418648d5005e82fd3b345d20d0",
    "time" : 1294031411,
    "difficulty" : 1.00000000,
}

# bitcoin-cli getblockhash 131039 | xargs bitcoin-cli getblock
{
    "hash" : "0000000000000e6e98694ccb8247aad63aaa1e2bec5a7be14329407e4cea6223",
    "time" : 1308145551,
    "difficulty" : 567269.53016242,
}

# bitcoin-cli getblockhash 131040 | xargs bitcoin-cli getblock
{
    "hash" : "000000000000097aa651b8e19c448924586a8010721c8e7ea282a0272d425987",
    "time" : 1308145774,
    "difficulty" : 876954.49351354,
}
</code></pre>

CC BY-SA 3.0
2016-01-07T16:35:12.413Z
2016-01-07T16:35:12.413Z
Dustin Butler
<p>You can get it for example on blockchain.info. Call up the <a href="https://blockchain.info/charts/difficulty?timespan=all" rel="nofollow">Difficulty chart</a>, switch the time-frame to "All Time", then use the link labelled "<a href="https://blockchain.info/charts/difficulty?showDataPoints=false&amp;timespan=all&amp;show_header=true&amp;daysAverageString=1&amp;scale=0&amp;format=csv&amp;address=" rel="nofollow">CSV</a>", to download it.</p>

<p>Note that the difficulty only changes every 2016 blocks, which is re-targeted to be about 14 days, in case you wonder why there are so few data points.</p>

CC BY-SA 3.0
2016-01-07T11:13:10.323Z
After having a look at the data, there may be a mistake in the first few data points. As far as I know the difficulty can’t drop below one, so the values given with zero irritate me. I would assume that they were one as well.
Murch
CC BY-SA 3.0
2016-01-07T11:27:52.633Z
Thank you! This is exactly what I was looking for. Also, I'll adjust the 0 values, as you describe, before using the data.
timeSmith
CC BY-SA 3.0
2016-01-07T21:30:30.600Z
I don't see any negative data points, but I do see a few 0 points. Bitcoin's difficulty can't go below 1 by consensus rule, I believe, so blockchain.info has some bad data here.
morsecoder
CC BY-SA 3.0
2016-01-07T11:07:20.440Z
2016-01-07T11:33:04.083Z
2016-01-07T11:33:04.083Z
Murch
<p>I would like to have a complete list of the historical mining difficulty of bitcoin. Preferably it would be a text list or csv, but a webpage that displays the data in any text format will do. </p>

<p>I've been searching for several hours over the last couple of days with no progress. I'm quite surprised that this is so hard to find...</p>

<difficulty>
Where, or how, can I get a complete history of difficulty?
timeSmith
# Where, or how, can I get a complete history of difficulty?

(Asked by: username_0 on 2016-01-07)

I would like to have a complete list of the historical mining difficulty of bitcoin. Preferably it would be a text list or csv, but a webpage that displays the data in any text format will do.

I've been searching for several hours over the last couple of days with no progress. I'm quite surprised that this is so hard to find...

**Tags:** difficulty


---

## 3 answers

### Answer by username_4 on 2016-01-07. Score: 3 | Accepted answer

You can get it for example on blockchain.info. Call up the [Difficulty chart](https://blockchain.info/charts/difficulty?timespan=all), switch the time-frame to "All Time", then use the link labelled "[CSV](https://blockchain.info/charts/difficulty?showDataPoints=false&timespan=all&show_header=true&daysAverageString=1&scale=0&format=csv&address=)", to download it.

Note that the difficulty only changes every 2016 blocks, which is re-targeted to be about 14 days, in case you wonder why there are so few data points.

> **Comments:**
> **username_4**: After having a look at the data, there may be a mistake in the first few data points. As far as I know the difficulty can’t drop below one, so the values given with zero irritate me. I would assume that they were one as well.  
> **username_0**: Thank you! This is exactly what I was looking for. Also, I'll adjust the 0 values, as you describe, before using the data.  
> **username_5**: I don't see any negative data points, but I do see a few 0 points. Bitcoin's difficulty can't go below 1 by consensus rule, I believe, so blockchain.info has some bad data here.  

---

### Answer by username_1 on 2022-09-13. Score: 3

I needed a trustworthy history of mining difficulty changes and also landed on the blockchain.info chart that clearly has incorrect (averaged) data. So I wrote this script that uses the Esplora API to search for difficulty changes. The logic could be easily ported to run against your own Esplora instance or your own Bitcoin node's RPC API.

Script is here: <https://github.com/jlopp/bitcoin-utils/blob/master/generateDifficultyHistoryCSV.php>

```
<?php

// This script uses the blockstream explorer API
// It iterates through every block that was minted after a difficulty retarget height
// and if the difficulty changed compared to the previous epoch, will print it in CSV format

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

$currentBlockHeight = 38304; // one epoch before the first difficulty change (speed up the script by reducing API calls)
$currentBlockHash = NULL;
$currentDifficulty = 1;

// determine where to stop looking for new difficulty epochs
curl_setopt($ch, CURLOPT_URL, "https://blockstream.info/api/blocks/tip/height");
$chainTipHeight = curl_exec($ch);
$maxBlockHeight = $chainTipHeight - ($chainTipHeight % 2016) - 2016;

echo "\nBlock Height,Date,Difficulty\n";
echo "0,2009-01-03,1\n";

while ($currentBlockHeight < $maxBlockHeight) {  // there are more difficulty retargets
    $currentBlockHeight += 2016;
    curl_setopt($ch, CURLOPT_URL, "https://blockstream.info/api/block-height/$currentBlockHeight");
    $currentBlockHash = curl_exec($ch);

    curl_setopt($ch, CURLOPT_URL, "https://blockstream.info/api/block/$currentBlockHash");
    $block = json_decode(curl_exec($ch));
    if ($block->difficulty != $currentDifficulty) {
        echo $block->height . "," . date("Y-m-d", $block->timestamp) . "," . $block->difficulty . "\n";
    }

}

```

> **Comments:**
> **username_2**: As it's only 34 lines, you could inline it here (with a note of where the latest version can be found) to avoid future issues with link-rot/404  

---

### Answer by username_3 on 2016-01-07. Score: 3

The data is also stored on the block chain. Query every 2016 blocks to see the difficulty at that time. Here are some samples, can see block 131040 was a re-target.

```
# bitcoin-cli getblockhash 4032 | xargs bitcoin-cli getblock
{
    "hash" : "00000000ca4b69045a03d7b20624def97a5366418648d5005e82fd3b345d20d0",
    "time" : 1294031411,
    "difficulty" : 1.00000000,
}

# bitcoin-cli getblockhash 131039 | xargs bitcoin-cli getblock
{
    "hash" : "0000000000000e6e98694ccb8247aad63aaa1e2bec5a7be14329407e4cea6223",
    "time" : 1308145551,
    "difficulty" : 567269.53016242,
}

# bitcoin-cli getblockhash 131040 | xargs bitcoin-cli getblock
{
    "hash" : "000000000000097aa651b8e19c448924586a8010721c8e7ea282a0272d425987",
    "time" : 1308145774,
    "difficulty" : 876954.49351354,
}

```


---

