EODHD gives you stocks, ETFs, forex, funds, indices, and bonds — 150,000+ tickers across 70+ exchanges, with 30+ years of history. This guide gets you from zero to your first data as fast as possible, whichever way you work: with AI tools, with code, or in a spreadsheet.
Coverage at a glance
EODHD covers stocks, ETFs, mutual funds, indices, forex, cryptocurrencies, and bonds — 150,000+ tickers across 70+ exchanges, with 30+ years of history.
Each API has its own coverage. Geography and asset classes differ from one endpoint to the next — for example, intraday history, live quotes, and fundamentals each reach a different set of markets, and some datasets are US-only while others are global. The exact coverage, supported exchanges, and history depth are documented on each API’s own page. Start with the full API documentation, and check the list of supported tickers and supported exchanges to confirm what is available for the market you need.
List the tickers and exchanges we cover
You can also pull the coverage lists programmatically. These endpoints return every exchange and every ticker we support, so you can confirm what is available before you build (they run with your own API key):
GET /api/exchanges-list/ # all supported exchanges
GET /api/exchange-symbol-list/{EXCHANGE} # every ticker on an exchange, e.g. US
GET /api/search/{query} # find a ticker by name or symbol
- Exchanges API — the full list of supported exchanges, with codes and trading hours.
- Exchange Symbols API — every ticker available on a given exchange.
- Search API — look up a ticker by company name or symbol across all markets.
Get your API key
Every request to EODHD is authenticated with your personal API token, passed as the api_token parameter (or set once inside an SDK, the MCP server, or a spreadsheet add-on). Without a token you can only use the shared demo token, which works for a handful of sample tickers.
Where to get it
- Create a free account at eodhd.com/register — no credit card required.
- Open your dashboard — your API token is shown there, and it also arrives in the welcome email.
- Copy it and use it in place of demo in any example below.
Just want to try it first? Use the demo token — it works for AAPL.US, TSLA.US, VTI.US, AMZN.US, MCD.US, and BTC-USD.CC, so you can run every example on this page without signing up. One real token then works everywhere: the API, the SDKs, the MCP server, and the spreadsheet add-ons.
https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Choose your fastest path
Pick the card that matches how you build — each one jumps to the section that gets you to real data fastest.
AI tools & vibe coders
- Connect the MCP server
- Or install the Claude Code plugin
- Ask for data in plain English
Direct API & SDKs
- Copy a curl call
- Or use the Python / Node SDK
- Browse the full documentation
No-code: spreadsheets & BI
- Install the add-on
- Pull data into a cell
- Build models & dashboards
AI tools & vibe coders
If you build with an AI assistant, you can get EODHD data without writing HTTP calls yourself. Ask in natural language and the tool fetches it for you — the fastest path for AI-first workflows.
MCP Server
The EODHD MCP Server exposes financial data as a set of read-only tools for any MCP-compatible client — Claude Desktop, Claude Code, Cursor, Windsurf, and ChatGPT connectors. It covers end-of-day, intraday, live quotes, fundamentals, news, screeners, technicals, corporate actions, macro, and more. Full setup and installation steps are in the MCP Server documentation.
Once connected, just ask your assistant in plain English, for example:
Claude Code plugin
The EODHD plugin for Claude Code is the batteries-included option. It bundles a hosted MCP server (OAuth — nothing to self-host) plus ready-made analysis workflows: skills for company briefs, earnings, market overview, screening, risk, and macro, a financial-analyst agent, and slash commands such as /eodhd-api:eodhd-analyze and /eodhd-api:eodhd-compare. Install it from inside Claude Code:
/plugin marketplace add EodHistoricalData/eodhd-claude-skills
/plugin install eodhd-api@eodhd-claude-skills
MCP server or Claude plugin — which one? Use the MCP server if you work in Cursor, Windsurf, Claude Desktop, or ChatGPT, or if you want raw data tools you wire up yourself. Use the Claude plugin if you work in Claude Code and want a one-command install plus ready-made analysis workflows and slash commands on top of the same data. The plugin uses the MCP server under the hood, so you are not choosing different data — only how much is set up for you.
ChatGPT Assistant
Our ChatGPT assistant is trained on the EODHD API documentation. It returns financial data directly in chat and generates working code in any language. Ask it, for example: “Write Python code to retrieve dividends for AAPL for 2024”.
AI tools use your own API token. The MCP server, the Claude Code plugin, and the ChatGPT assistant all authenticate with the same key you use for the API. That means an AI tool can reach exactly the data your subscription covers — the same endpoints, markets, and history — and nothing beyond it, with the same daily API-call quota and rate limits applied. Keep your token private and treat it like a password.
Direct API & SDKs
Here is your first request, returning end-of-day data for the AAPL ticker. If you are logged in, the request line below already contains your own API key; if not, it uses the demo token. Switch tabs for cURL, PHP, Python, or R, or open the request in a new tab.
https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Prefer a library? One line to install:
pip install eodhd # Python
npm install eodhd-apis # Node.js / TypeScript
Official libraries are also available for .NET, R, PHP, and Java, plus a Postman collection — see all SDKs and code examples.
Every API has its own detailed guide. The full API documentation has a dedicated page for each endpoint — parameters, response fields, and worked examples for how to use it. Start there whenever you pick up a new dataset.
No-code: spreadsheets & BI
Not a developer? Pull prices, fundamentals, and historical data straight into your spreadsheets or dashboards — no code required.
- Google Sheets Add-on — live and historical data in Sheets, on Windows, Mac, and Linux.
- Excel Add-in — quotes, history, and fundamentals in cells, for Windows.
- Power BI Connector — dashboards and reports.
Try it — popular endpoints
Run real requests right now — all of these use the demo token, so you can test them in your browser before signing up. Each one links to its full documentation.
- You can start with "DEMO" API key to test the data for a few tickers only: AAPL.US, TSLA.US, VTI.US, AMZN.US, BTC-USD.CC and EURUSD.FOREX. For these tickers, all of our types of data (APIs), including Real-Time Data, are available without limitations.
- Register for the free plan to receive your API key (limited to 20 API calls per day) with access to End-Of-Day Historical Stock Market Data API for any ticker, but within the past year only. Plus a List of tickers per Exchange is available.
- We recommend to explore our plans, starting from $19.99, to access the necessary type of data without limitations.
End-of-day historical prices — 30+ years of daily OHLCV. Documentation
https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Live (delayed) price — latest quote snapshot. Documentation
https://eodhd.com/api/real-time/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/real-time/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/real-time/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/real-time/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/real-time/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Fundamentals — financials, ratios, and earnings. Documentation
https://eodhd.com/api/fundamentals/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/fundamentals/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/fundamentals/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/fundamentals/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/fundamentals/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Intraday bars — 1m to 1h OHLCV within the trading day. Documentation
https://eodhd.com/api/intraday/AAPL.US?api_token=demo&interval=5m&fmt=json
curl --location "https://eodhd.com/api/intraday/AAPL.US?api_token=demo&interval=5m&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/intraday/AAPL.US?api_token=demo&interval=5m&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/intraday/AAPL.US?api_token=demo&interval=5m&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/intraday/AAPL.US?api_token=demo&interval=5m&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Dividends & splits — corporate actions history. Documentation
https://eodhd.com/api/div/AAPL.US?api_token=demo&fmt=json
curl --location "https://eodhd.com/api/div/AAPL.US?api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/div/AAPL.US?api_token=demo&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/div/AAPL.US?api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/div/AAPL.US?api_token=demo&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Technical indicators — SMA, RSI, and more, computed for you. Documentation
https://eodhd.com/api/technical/AAPL.US?api_token=demo&function=sma&fmt=json
curl --location "https://eodhd.com/api/technical/AAPL.US?api_token=demo&function=sma&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/technical/AAPL.US?api_token=demo&function=sma&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/technical/AAPL.US?api_token=demo&function=sma&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/technical/AAPL.US?api_token=demo&function=sma&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
Commodities — historical prices for oil, gas, metals, and agriculture. Documentation
https://eodhd.com/api/commodities/historical/WTI?api_token=demo&interval=monthly&fmt=json
curl --location "https://eodhd.com/api/commodities/historical/WTI?api_token=demo&interval=monthly&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/commodities/historical/WTI?api_token=demo&interval=monthly&fmt=json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$data = curl_exec($curl);
curl_close($curl);
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
var_dump($data);
} catch (Exception $e) {
echo 'Error. '.$e->getMessage();
}
import requests
url = f'https://eodhd.com/api/commodities/historical/WTI?api_token=demo&interval=monthly&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/commodities/historical/WTI?api_token=demo&interval=monthly&fmt=json'
response <- GET(url)
if (http_type(response) == "application/json") {
content <- content(response, "text", encoding = "UTF-8")
cat(content)
} else {
cat("Error while receiving data\n")
}
Try it now (it's free)!
How to use it (YouTube)
How usage works
API calls work like a currency. Every request spends calls from your daily quota, and there is also a per-minute request limit. Most endpoints cost 1 API call per request; data-heavy ones cost more — for example intraday, technical, and news cost 5 calls each, and fundamentals and options cost 10.
- Free plan — 20 API calls per day.
- Paid plans — 100,000 API calls per day by default.
- Rate limit — up to 1,000 requests per minute on every plan.
Need more headroom? You have two options, both in your dashboard:
- Buy extra API calls — a buffer that is used only after your daily limit is exhausted. Extra calls do not expire and accumulate as you add more.
- Increase your daily limit — raise the default daily cap for your plan from the “Daily Usage” section.
Trying the examples on this page is cheap. See the full breakdown, including the exact cost of each endpoint, in the API Limits article.
Community & learning
The EODHD Academy is where you go from data to results — 160+ step-by-step tutorials on trading strategies, data analysis, and using AI in finance, most with ready-to-run code. It is the fastest way to see how other developers and analysts put EODHD data to work.
And you are not building alone — join the community to ask questions, share what you build, and keep up with new data and features.
Questions, project showcases, data tips, and product updates — from developers and analysts using EODHD every day.
Next steps
- Building with AI? Connect the MCP server or install the Claude Code plugin.
- Writing code? Grab a library and browse the full API documentation.
- Going to production? Review pricing and plans and pick the one that fits.
Questions? Our 24/7 live support team (real humans) is one click away — use the chat in the lower-right corner of any page, or email support@eodhistoricaldata.com.