Free & Open Data API
The same data and math behind this calculator, as plain HTTP endpoints. Daily BTC/USD history back to 2010 and full DCA backtests, in JSON or CSV. No API keys, no accounts, no signup wall.
Why This Is Free
Getting clean Bitcoin price history usually means an API key, a credit card on file, and a rate-limit table. That's a strange gatekeeping ritual for numbers that were public the moment they happened. This site already assembles the series for its own calculator, so republishing it costs almost nothing — and the whole project is open source, so hiding the data behind a key would be theater anyway.
There is deliberately no auth and no rate-limit code. Responses are cached at the CDN edge (an hour for prices, 30 minutes for backtests), so repeated identical requests never even reach the server. The cache is the protection. Hammering an endpoint mostly means hammering a cache.
Endpoints
All endpoints answer GET and OPTIONS, send Access-Control-Allow-Origin: * so browser fetch() works from any origin, and return errors as JSON with a plain-English error message. Every parameter is optional.
/api/v1/prices
Daily BTC/USD closes as JSON: one [utcMidnightMs, close] pair per UTC day. Defaults to the full history, 2010-08-18 to today.
| Param | Accepts | Default |
|---|---|---|
| from | ISO date (yyyy-MM-dd), clamped to 2010-08-18 at the early end | 2010-08-18 |
| to | ISO date, clamped to today at the late end | today |
| provider | kraken or coinbase | kraken |
curl 'https://btcdollarcostaverage.com/api/v1/prices?from=2020-01-01&to=2020-12-31'Try it live: /api/v1/prices?from=2024-01-01&to=2024-06-30
Response shape (values illustrative):
{
"source": "kraken",
"asOf": "2026-08-11T09:00:00.000Z",
"from": "2020-01-01",
"to": "2020-12-31",
"count": 366,
"note": "All prices are USD, one close per UTC day. ...",
"series": [
[1577836800000, 7174.33],
[1577923200000, 6965.71]
]
}/api/v1/prices.csv
The exact same series as a downloadable CSV with date,usd rows — one row per UTC day, ready for a spreadsheet or pandas. Same parameters as /api/v1/prices.
curl -o btc-usd-daily.csv 'https://btcdollarcostaverage.com/api/v1/prices.csv?provider=coinbase'Try it live: /api/v1/prices.csv?from=2024-01-01&to=2024-06-30
date,usd
2024-01-01,44187.14
2024-01-02,44946.91
2024-01-03,42845.23Prices are rounded to cents (four decimals below $1, so the 2010–2011 era doesn't flatten to zero). The JSON endpoint returns unrounded values. The body is pure data — the provenance note travels in an X-Data-Note response header instead of comment rows.
/api/v1/dca
A full DCA backtest — the same engine, same price pipeline, and same defaults as the on-site calculator ($50 every week for the last 5 years at a 0.5% fee).
| Param | Accepts | Default |
|---|---|---|
| amount | USD per purchase, > 0 | 50 |
| frequency | daily, weekly, biweekly, monthly | weekly |
| startDate | ISO date, clamped to 2010-08-18 at the early end | 5 years before endDate |
| endDate | ISO date — future dates are clamped to today (this endpoint reports history only; the response flags the clamp) | today |
| fee | exchange fee %, 0 to 50 | 0.5 |
| provider | kraken or coinbase | kraken |
| startingBtc | BTC already held at the start date, > 0 | none |
| startingCost | USD cost per BTC for the starting stack; omitted, the stack is costed at the start date’s price | start-date price |
| esc | yearly purchase increase %, 0 to 200 — steps up on each 12-month anniversary. Out-of-range numeric params are clamped to their documented bounds | 0 |
curl 'https://btcdollarcostaverage.com/api/v1/dca?amount=100&frequency=weekly&startDate=2020-01-01&endDate=2024-12-31&fee=0.5'Try it live: /api/v1/dca?amount=100&frequency=weekly&startDate=2020-01-01&endDate=2024-12-31
Response shape (values illustrative):
{
"inputs": {
"amountUsd": 100, "frequency": "weekly",
"startDate": "2020-01-01", "endDate": "2024-12-31",
"feePercent": 0.5, "provider": "kraken"
},
"asOf": "2026-08-11T09:00:00.000Z",
"currency": "USD",
"totalInvested": 26100,
"btcAccumulated": 0.9273,
"averageCost": 28146.02,
"currentValue": 86518.44,
"profit": 60418.44,
"roiPercent": 231.49,
"xirrPercent": 48.7,
"maxDrawdownPercent": 62.4,
"purchaseCount": 261,
"spotPriceUsd": 93301.5,
"breakdownSampled": false,
"breakdown": [
{
"date": "2020-01-01T00:00:00.000Z",
"price": 7174.33,
"invested": 100,
"totalInvested": 100,
"accumulated": 0.01387,
"totalAccumulated": 0.01387,
"portfolioValue": 99.5
}
],
"note": "All figures are USD. ..."
}xirrPercent is the money-weighted annualized return, null for windows under 90 days. breakdown lists one row per purchase, capped at ~2,000 rows: longer schedules are evenly thinned (breakdownSampled: true, final purchase always kept, cumulative columns exact at every kept row), while purchaseCount stays the true total. The math itself is documented on the methodology page.
The Honest Bits
Where the prices come from. 2010-08-18 through 2015-07-19 are real daily closes from a bundled blockchain.info snapshot — that history no longer changes, so it ships with the site. From 2015-07-20 onward the series comes from the exchange you pick: Coinbase gives real daily candles; Kraken gives weekly closes that we linearly interpolate to daily, which smooths intra-week moves. If you need genuine day-by-day prices for the modern era, use provider=coinbase. Every response repeats this in its note field, so a downloaded series can't be mistaken for something it isn't.
Outages fall back silently. If the exchange you asked for is unreachable, the server serves the other exchange's series — or an up-to-an-hour-stale cache — rather than failing. That's the right trade for availability, but it means the response cannot guarantee which exchange actually produced it during an outage.
USD only. Every number in every endpoint is US dollars. The site's other display currencies are a display-time conversion, and pretending the API had native EUR or JPY series would be dishonest.
Freshness. Price responses are edge-cached for up to an hour, backtests for up to 30 minutes, and both may be served stale for up to a day while revalidating. The series gains one candle per day, so this costs you almost nothing — but don't use these endpoints as a live ticker.
Fair Use
No keys and no quotas means this runs on good faith. Cache responses on your side, fetch the full history once instead of a thousand slices, and don't poll faster than the cache windows above — you'd only be re-downloading identical bytes. If you build something on top of this, a link back to btcdollarcostaverage.com is appreciated but not required. If your use case needs more than this (bulk, streaming, something odd), get in touch — the answer is probably yes.
Open Source
The entire site, these endpoints included, is MIT-licensed. Don't trust the numbers? Read the code that produced them, or run your own copy:
Prefer Buttons to curl?
Everything the API computes, the calculator shows with charts. Same data, same math.
Open the CalculatorDisclaimer: This API serves an educational simulation and historical market data, not investment advice. Historical and simulated performance does not guarantee future results. The data is provided as-is, with no uptime or accuracy guarantees. Bitcoin is volatile and carries significant risk.