Every new account receives $125 in free data credits. These credits allow you to start receiving actual historical data immediately and verify your integration at no cost.
Choose a service
Databento provides two data services: historical and live. These two services are nearly identical, but we separate them due to licensing fees and the differences between response-request and real-time streaming APIs. You can choose to integrate just one or both services.
| Historical | Live | Reference | |
|---|---|---|---|
| Coverage | Data from at least 24 hours ago. | Intraday historical data from within the last 24 hours and real-time data. | Historical with intraday updates. |
| Pricing | Usage-based or flat-rate. No monthly license fees. | Usage-based or flat-rate. Monthly license fees apply. | Dataset license fees apply. |
| Access | Client libraries (C++, Python, and Rust) and API (HTTP). | Client libraries (C++, Python, and Rust) and API (Raw). | Client libraries (Python) and API (HTTP). |
Getting historical data
Select how you will be integrating Databento below to see installation instructions.
If you don't see an official client library for your preferred language, you can still integrate our historical service through its HTTP API.
Add our Rust client to your project's dependencies with cargo.
A simple Databento application looks like this.
This replays 10 minutes of trades of the entire CME Globex market event-by-event.
Copy this to a file named main.rs, then compile and run the application.
use databento::{
dbn::{Schema, TradeMsg},
historical::timeseries::GetRangeParams,
HistoricalClient, Symbols,
};
use time::macros::datetime;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut client = HistoricalClient::builder()
.key("YOUR_API_KEY")?
.build()?;
let mut decoder = client
.timeseries()
.get_range(
&GetRangeParams::builder()
.dataset("GLBX.MDP3")
.date_time_range((
datetime!(2022-06-10 14:30 UTC),
datetime!(2022-06-10 14:40 UTC),
))
.symbols(Symbols::All)
.schema(Schema::Trades)
.build(),
)
.await?;
while let Some(trade) =
decoder.decode_record::<TradeMsg>().await?
{
println!("{trade:?}");
}
Ok(())
}
You can modify this application to specify particular instruments, and schemas,
Let's get ESM2 and NQZ2 data in 1-second OHLCV bars.
use databento::{
dbn::{OhlcvMsg, Schema},
historical::timeseries::GetRangeParams,
HistoricalClient,
};
use time::macros::datetime;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut client = HistoricalClient::builder()
.key("YOUR_API_KEY")?
.build()?;
let mut decoder = client
.timeseries()
.get_range(
&GetRangeParams::builder()
.dataset("GLBX.MDP3")
.date_time_range((
datetime!(2022-06-10 14:30 UTC),
datetime!(2022-06-10 14:40 UTC),
))
.symbols(vec!["ESM2", "NQZ2"])
.schema(Schema::Ohlcv1S)
.build(),
)
.await?;
while let Some(bar) =
decoder.decode_record::<OhlcvMsg>().await?
{
println!("{bar:?}");
}
Ok(())
}
You have successfully written your first historical data application with Databento! Here are shortcuts to some of the next steps you can take:
- To download a large amount of data to disk, see how to do a batch download of data files.
- To get another dataset, just swap the dataset. You can get a list of datasets and their names from our metadata.
- You can use our symbology API to find other instrument IDs.
- You can also find dataset names and instrument IDs interactively from our search.
To learn more, read the full documentation for our historical service under API reference - Historical.
Getting live data
Select how you will be integrating Databento below to see installation instructions.
If you don't see an official client library for your preferred language, you can still integrate our service via the Raw API.
Add our Rust client to your project's dependencies with cargo.
A simple Databento live application looks like this.
This will stream and print trades for E-mini S&P 500 futures contracts, event-by-event, for 10 seconds.
Copy this to a file named main.rs, then compile and run the application.
use std::time::{Duration, Instant};
use databento::{
dbn::{PitSymbolMap, SType, Schema, TradeMsg},
live::Subscription,
LiveClient,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut client = LiveClient::builder()
.key("YOUR_API_KEY")?
.dataset("GLBX.MDP3")
.build()
.await?;
client
.subscribe(
Subscription::builder()
.symbols("ES.FUT")
.schema(Schema::Trades)
.stype_in(SType::Parent)
.build(),
)
.await?;
client.start().await?;
let mut symbol_map = PitSymbolMap::new();
let now = Instant::now();
while let Some(rec) = client.next_record().await? {
if let Some(trade) = rec.get::<TradeMsg>() {
let symbol = &symbol_map[trade.hd.instrument_id];
println!("Received trade for {symbol}: {trade:?}");
} else {
symbol_map.on_record(rec)?;
}
if now.elapsed() > Duration::from_secs(10) {
break;
}
}
Ok(())
}
You can modify this application to specify other instruments and schemas.
Let's get ESZ4 and ESZ4 C4000 data in 1-second OHLCV bars.
We'll also handle unexpected messages and errors in case something goes wrong.
Since we're handling more messages, it makes sense to change to a match expression based on
the rtype or record type field in the header of each record.
use std::time::{Duration, Instant};
use databento::{
dbn::{
ErrorMsg, OhlcvMsg, PitSymbolMap, RType, Record, Schema,
},
live::Subscription,
LiveClient,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut client = LiveClient::builder()
.key_from_env()?
.dataset("GLBX.MDP3")
.build()
.await?;
client
.subscribe(
Subscription::builder()
.symbols(vec!["ESZ5", "ESZ5 C6000"])
.schema(Schema::Ohlcv1S)
.start(time::OffsetDateTime::UNIX_EPOCH)
.build(),
)
.await?;
client.start().await?;
let mut symbol_map = PitSymbolMap::new();
let now = Instant::now();
while let Some(rec) = client.next_record().await? {
match rec.rtype()? {
RType::Ohlcv1S => {
let bar = rec.get::<OhlcvMsg>().unwrap();
println!(
"Received bar for {}: {bar:?}",
symbol_map[bar.hd.instrument_id]
);
}
RType::SymbolMapping => {
symbol_map.on_record(rec)?;
}
RType::System => {
break;
}
RType::Error => {
eprintln!(
"Received error from gateway: {}",
rec.get::<ErrorMsg>().unwrap().err()?
);
break;
}
rtype => {
eprintln!("Received record with unexpected rtype {rtype:?}");
}
}
if now.elapsed() > Duration::from_secs(10) {
break;
}
}
Ok(())
}
You have successfully written your first live data application with Databento! To learn more, read the full documentation for our live service under API reference - Live.
Getting reference data
Select how you will be integrating Databento below to see installation instructions.
If you don't see an official client library for your preferred language, you can still integrate our reference service through its HTTP API.
Add our Rust client to your project's dependencies with cargo.
use databento::{
reference::{corporate::GetRangeParams, Country, Event},
ReferenceClient,
};
use time::macros::date;
let mut client =
ReferenceClient::builder().key("YOUR_API_KEY")?.build()?;
let corporate_actions = client
.corporate_actions()
.get_range(
&GetRangeParams::builder()
.symbols("MSFT")
.start(date!(2019 - 01 - 01))
.end(date!(2024 - 08 - 01))
.events([Event::Div])
.countries([Country::Us])
.build(),
)
.await?;
println!("{corporate_actions:#?}");
You have successfully written your first reference data application with Databento! Here are shortcuts to some of the next steps you can take:
- Read the corporate actions dataset guide.
- Become familiar with the reference data enum lookup tables.
- Go through the corporate actions examples.
To learn more, read the full documentation for our reference service under Reference API.