The Tick Data API returns individual trades on the US equity market — one record per execution, with a millisecond timestamp, the price, the size, the venue that printed it and the sale conditions that qualify it. History reaches back to the first trading day of 2008, and the data covers every US venue rather than a single exchange feed.
Coverage spans approximately 80,000 tickers — current and delisted companies alike — with 16,000+ securities updated every trading day, and the archive now holds roughly 10 terabytes of history in total. It keeps growing with every session added.
This is the raw material for market-microstructure work: measuring spreads and price impact, reconstructing the tape, backtesting at the execution level, and separating on-exchange prints from off-exchange ones. Note the response shape before you write a parser — ticks come back as parallel arrays, one array per field, not as a list of objects.
Requesting ticks
- 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.
https://eodhd.com/api/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=1000&api_token=YOUR_API_TOKEN&fmt=json
Parameters
api_token
string
required
s
string
optional
from
integer
optional
to
integer
optional
limit
integer
optional
fmt
enum
optional
Two units in one endpoint: from and to are UNIX timestamps in seconds, UTC, while the ts field in the response is in milliseconds. Divide by 1000 before feeding a returned timestamp back into a query. Always pass both bounds explicitly — when they are omitted the endpoint falls back to yesterday, and on a non-trading day that fallback returns HTTP 404.
The 10,000 ceiling applies only when you pass limit — omitting it removes the cap entirely. The full AAPL session of 11 September 2023 comes back as 722,444 ticks in a 33 MB response, and it still costs one API call however large it is. Decide deliberately which you want.
To walk a long window in slices, page on seq rather than on time — but scope the paging to one trading day. seq is unique and strictly increasing within a session and resets at the start of the next one: in a single response spanning two sessions it drops from 511,729,487 back to 65,050, and 32 ticks end up sharing a seq with a trade from the other day. Time is no better as a cursor, because ts repeats — 56% of the ticks in that AAPL session share a millisecond with another trade.
Both bounds are inclusive, and they are compared in milliseconds: a tick is returned when from × 1000 ≤ ts ≤ to × 1000. Two consequences worth knowing. A request where from equals to matches only trades landing on that exact millisecond, so in practice it comes back empty. And two adjacent slices that share a boundary second both contain the trades printed in that second — advance from by one second, or de-duplicate on seq within the day.
Results arrive in time order: ts never decreases through a response, though it does repeat, while seq strictly increases within a session. An empty window is not an error — it returns HTTP 200, and the body is either the usual object with seven empty arrays or a bare empty JSON array, so accept both shapes. HTTP 404 means something else: an unknown symbol, a non-US symbol, a delisted symbol that falls outside tick coverage, or the yesterday fallback described above. And whatever you pass in fmt, the response is JSON.
Request Example
https://eodhd.com/api/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=5&api_token=demo&fmt=json
curl --location "https://eodhd.com/api/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=5&api_token=demo&fmt=json"
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://eodhd.com/api/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=5&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/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=5&api_token=demo&fmt=json'
data = requests.get(url).json()
print(data)
library(httr)
library(jsonlite)
url <- 'https://eodhd.com/api/ticks/?s=AAPL&from=1694455200&to=1694541600&limit=5&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)
The demo token covers a limited set of tickers — AAPL, MSFT, TSLA and AMZN all respond — and returns HTTP 403 for anything outside it, GOOGL and SPY included. Use your own token for anything beyond a first look.
Response Example
{
"mkt": ["V", "V", "Q", "Q", "H"],
"price": [179.25, 179.25, 179.25, 179.25, 179.25],
"seq": [376150475, 376150494, 376151129, 376151173, 376153538],
"shares": [100, 100, 100, 32, 9],
"sl": ["@ ", "@ ", "@F ", "@F I", "@F I"],
"sub_mkt": ["", "", "", "", ""],
"ts": [1694455200017, 1694455200017, 1694455200017, 1694455200017, 1694455200023]
}
Every array has the same length and the same ordering, so tick n is the combination of index n across all seven arrays. The first tick above is 100 shares at 179.25 on venue V, a regular sale with no qualifiers. Two details are visible straight away: the first four trades all carry the same millisecond, and the fourth and fifth are odd lots — 32 and 9 shares — which is what the trailing I in sl marks.
Response Fields
| Field | Type | Description |
|---|---|---|
| ts | integer | Trade timestamp, milliseconds since the UNIX epoch, UTC |
| price | number | Execution price |
| shares | integer | Size of the trade in shares. Sizes below 100 are odd lots and are flagged with I in sl |
| mkt | string | Venue that reported the trade, as a single-character participant code — see the table below |
| sub_mkt | string | Reporting facility, filled in exactly when mkt is D and empty for every on-exchange print |
| sl | string | Sale conditions — a fixed-width four-position field holding several codes at once, not a single code. Spaces are meaningful padding. See the section below |
| seq | integer | Trade sequence number — unique and strictly increasing within a trading session, and reset at the start of the next one. The right cursor for paging inside a single day, but not unique across days |
Sale conditions — the sl field
This is the field most likely to break a parser. sl is not one code — it is a fixed-width string of four positions, and a single trade commonly carries several conditions at once. Each position holds a different family of codes:
| Position | What it carries | Values seen in one full AAPL session |
|---|---|---|
| 1 | Trade type | @ regular sale on almost every print, plus C cash sale and N next day. It can also be blank — in 2008 history several hundred prints a day leave it empty |
| 2 | Execution qualifier | Blank, F intermarket sweep, and the digits 4, 6 and 7 |
| 3 | Timing | Blank, T form T (outside regular hours), Z sold out of sequence |
| 4 | Size and price qualifier | I odd lot, W average price, V contingent trade, P prior reference price, and occasionally Q, M and X |
The five most frequent values in that session, in order, were @ I (regular sale, odd lot — 412,430 prints), @ alone (regular sale, no qualifiers — 120,061), @F I (sweep and odd lot — 84,916), @F (sweep — 65,162) and @ TI (outside regular hours, odd lot — 18,671). Thirty-two distinct values appeared in the day in total.
Read each position independently and trim the padding rather than comparing the whole string, and keep values you cannot decode: the digits that turn up in position 2 are not in the code list below, which covers letters only. The individual letter codes are:
| Code | Condition | Code | Condition |
|---|---|---|---|
| @ | Regular Sale | N | Next Day |
| A | Acquisition | O | Opening Prints |
| B | Bunched Trade | P | Prior Reference Price |
| C | Cash Sale | Q | Market Center Official Open |
| D | Distribution | R | Seller |
| E | Placeholder | S | Split Trade |
| F | Intermarket Sweep | T | Form T |
| G | Bunched Sold Trade | U | Extended trading hours, sold out of sequence |
| H | Price Variation Trade | V | Contingent Trade |
| I | Odd Lot Trade | W | Average Price Trade |
| K | Rule 155 Trade (AMEX) | X | Cross or Periodic Auction Trade |
| L | Sold Last | Y | Yellow Flag Regular Trade |
| M | Market Center Official Close | Z | Sold, out of sequence |
Venue codes — the mkt field
| Code | Venue | Code | Venue |
|---|---|---|---|
| A | NYSE American, LLC | M | Chicago Stock Exchange |
| B | NASDAQ BX, Inc. | N | New York Stock Exchange, LLC |
| C | NYSE National, Inc. | P | NYSE Arca, Inc. |
| D | FINRA Alternative Display Facility | Q | The NASDAQ Stock Market, LLC |
| E | Market Independent | S | Consolidated Quotation System |
| H | MIAX Exchange | T | The NASDAQ Stock Market, LLC |
| I | International Securities Exchange | U | Members Exchange |
| J | Cboe EDGA Exchange, Inc. | W | Cboe Stock Exchange |
| K | Cboe EDGX Exchange, Inc. | X | NASDAQ PSX, Inc. |
| L | Long-term Stock Exchange | Y | Cboe BYX Exchange, Inc. |
| u | Other OTC Markets | Z | Cboe BZX Exchange, Inc. |
The list above is the published mapping and it is not exhaustive — V, for one, is absent from it and accounted for about 1% of prints in the AAPL session used throughout this page. Treat mkt as an opaque single character and keep codes you do not recognise rather than discarding those trades. Expect most volume to be reported off-exchange, too: code D was 57% of ticks in that session, more than every exchange combined, and every D row carries a reporting facility in sub_mkt.
Reporting facility — the sub_mkt field
| Code | Facility |
|---|---|
| (empty) | On-exchange print — mkt is not D, so no reporting facility is involved |
| Q | FINRA/Nasdaq Trade Reporting Facility, Carteret |
| N | FINRA/NYSE Trade Reporting Facility |
| B | FINRA/Nasdaq Trade Reporting Facility, Chicago |
Where to go next
Tick data is the finest granularity we publish. One step coarser is the Intraday Historical Data API, with one-minute, five-minute and one-hour bars; coarser still is the End-of-Day API. For a live stream rather than history, see the Real-Time Data API via WebSockets.
To find the symbols this API accepts, list the US universe with the Exchanges API, and check how requests are counted against your plan in API Limits.
Tick Data is also sold on its own, without a full EODHD subscription, as a standalone product on our Marketplace — useful if trade-level US history is the only dataset you need. The sidebar links to the product page.