# Quickstart

![](https://2257279413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LihqQrMLN4ia7KgxAzi%2Fuploads%2Fgit-blob-676d487503d820f88d42f05314b4d7a473fa5f9b%2Fexcalidraw-2020316131859%20\(1\).png?alt=media)

[Tardis-machine](https://github.com/tardis-dev/tardis-machine) is a locally runnable server with built-in data caching that uses Tardis.dev [HTTP API](https://docs.tardis.dev/api/http-api-reference) under the hood. It provides both tick-level historical and consolidated real-time cryptocurrency market data via its HTTP and WebSocket APIs and is available via [npm](#npm) and [Docker](#docker).

## Features

* efficient data replay API endpoints returning historical market data for whole time periods (in contrast to Tardis.dev [HTTP API](https://docs.tardis.dev/api/http-api-reference) where single call returns data for single minute time period)
* [exchange-native market data APIs](https://docs.tardis.dev/replaying-historical-data#exchange-native-market-data-apis)
  * tick-by-tick historical market data replay in [exchange-native format](https://docs.tardis.dev/faq/data#what-is-a-difference-between-exchange-native-and-normalized-data-format)
  * [HTTP](https://docs.tardis.dev/replaying-historical-data#http-get-replay-options-options) and [WebSocket](https://docs.tardis.dev/replaying-historical-data#websocket-ws-replay-exchange-exchange-and-from-fromdate-and-to-todate) endpoints
  * [WebSocket API](https://docs.tardis.dev/replaying-historical-data#websocket-ws-replay-exchange-exchange-and-from-fromdate-and-to-todate) providing historical market data replay from any given past point in time with the same data format and 'subscribe' logic as real-time exchanges' APIs - in many cases **existing exchanges' WebSocket clients can be used to connect to this endpoint**
* [normalized market data APIs](https://docs.tardis.dev/replaying-historical-data#normalized-market-data-apis)
  * consistent format for accessing market data across multiple exchanges
  * [HTTP](https://docs.tardis.dev/replaying-historical-data#http-get-replay-normalized-options-options) and [WebSocket](https://docs.tardis.dev/replaying-historical-data#websocket-ws-replay-normalized-options-options) endpoints
  * synchronized [historical market data replay across multiple exchanges](https://docs.tardis.dev/replaying-historical-data#http-get-replay-normalized-options-options)
  * [consolidated real-time data streaming](https://docs.tardis.dev/tardis-machine/streaming-real-time-data) connecting directly to exchanges' WebSocket APIs
  * customizable [order book snapshots](https://docs.tardis.dev/data-types#book_snapshot_-number_of_levels-_-snapshot_interval-time_unit) and [trade bars](https://docs.tardis.dev/data-types#trade_bar_-aggregation_interval-suffix) data types
* [seamless switching between real-time data streaming and historical data replay](https://docs.tardis.dev/replaying-historical-data#normalized-market-data-apis)
* transparent historical local data caching (cached data is stored on disk in compressed format and decompressed on demand when reading the data)
* support for top cryptocurrency exchanges: [BitMEX](https://docs.tardis.dev/historical-data-details/bitmex), [Deribit](https://docs.tardis.dev/historical-data-details/deribit), [Binance Spot](https://docs.tardis.dev/historical-data-details/binance), [Binance USDS-M Futures](https://docs.tardis.dev/historical-data-details/binance-futures), [OKX Spot](https://docs.tardis.dev/historical-data-details/okex), [HTX Spot](https://docs.tardis.dev/historical-data-details/huobi), [bitFlyer](https://docs.tardis.dev/historical-data-details/bitflyer), [Bitstamp](https://docs.tardis.dev/historical-data-details/bitstamp), [Coinbase Exchange](https://docs.tardis.dev/historical-data-details/coinbase), [Kraken Futures (Crypto Facilities)](https://docs.tardis.dev/historical-data-details/cryptofacilities), [Gemini](https://docs.tardis.dev/historical-data-details/gemini), [Kraken](https://docs.tardis.dev/historical-data-details/kraken), [Bitfinex](https://docs.tardis.dev/historical-data-details/bitfinex), [Bybit Derivatives](https://docs.tardis.dev/historical-data-details/bybit) and more
* [Open Source](https://github.com/tardis-dev/tardis-machine)

{% embed url="<https://github.com/tardis-dev/tardis-machine>" %}
Tardis-machine GitHub repository
{% endembed %}

{% hint style="info" %}
Real-time streaming via tardis-machine is available only in [normalized format](https://docs.tardis.dev/tardis-machine/streaming-real-time-data). Exchange-native (raw) real-time data is not provided. If you need raw real-time feeds, connect directly to exchange WebSocket APIs.
{% endhint %}

## Installation

### **Docker**

Pull and run latest version of [`tardisdev/tardis-machine` image](https://hub.docker.com/r/tardisdev/tardis-machine):

```bash
### running without persistent local cache
docker run -p 8000:8000 -p 8001:8001 -e "TM_API_KEY=YOUR_API_KEY" -d tardisdev/tardis-machine
```

Tardis-machine server's HTTP endpoints will be available on port `8000` and WebSocket API endpoints on port `8001`. Your API key will be passed via environment variable (`TM_API_KEY`) — simply replace `YOUR_API_KEY` with the API key you've received via email.

The command above does not use persistent volumes for local caching (each Docker restart will result in losing local data cache). To use `./host-cache-dir` as a persistent volume ([bind mount](https://docs.docker.com/storage/bind-mounts/)) cache directory, run:

```bash
docker run -v ./host-cache-dir:/.cache -p 8000:8000 -p 8001:8001 -e "TM_API_KEY=YOUR_API_KEY" -d tardisdev/tardis-machine
```

Since using volumes can cause issues especially on Windows, it's fine to run Docker image without them with the caveat of potentially poor local cache ratio after each container's restart.

#### Config environment variables

You can set the following environment variables to configure tardis-machine server:

| name                  | default   | description                                                                                                                                                                     |
| --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **TM\_API\_KEY**      |           | API key for [Tardis.dev](https://tardis.dev/) HTTP API - if not provided only first day of each month of historical data is accessible                                          |
| **TM\_PORT**          | `8000`    | HTTP port on which server will be running, **WebSocket port is always this value + 1** (`8001` with port set to `8000`)                                                         |
| **PORT**              |           | if set, overrides the configured port from `TM_PORT` or `--port`; useful on platforms that inject `PORT` automatically                                                          |
| **TM\_CACHE\_DIR**    | `/.cache` | path to local dir that will be used as cache location                                                                                                                           |
| **TM\_CLUSTER\_MODE** | `false`   | will launch [cluster of Node.js processes](https://nodejs.org/api/cluster.html) to handle the incoming requests if set to `true`, by default server runs in single process mode |
| **TM\_DEBUG**         | `false`   | server will print verbose debug logs to stdout if set to `true`                                                                                                                 |
| **TM\_CLEAR\_CACHE**  | `false`   | server will clear local cache dir on startup if set to `true`                                                                                                                   |

{% hint style="info" %}
The local cache grows without limit by default. For large backfills this can consume significant disk space. Use `TM_CLEAR_CACHE=true` to clear the cache on startup, or set `autoCleanup: true` in [replay options](https://docs.tardis.dev/replaying-historical-data#replay-options) to remove cached data after each replay completes. See the [replay options](https://docs.tardis.dev/replaying-historical-data#replay-options) section for `autoCleanup` concurrency caveats.
{% endhint %}

Tardis-machine also supports exchange-specific environment variables (exchange credentials, proxy, WebSocket URL overrides, Binance rate limit tuning) — see the [Node.js client environment variables](https://docs.tardis.dev/node-client/normalization#environment-variables-advanced) for the full list.

### **npm**

{% hint style="info" %}
Requires Node.js v24+ and git installed.
{% endhint %}

{% hint style="info" %}
Node.js examples in this section use ES modules and top-level await. Save snippets as `.mjs` or set `"type": "module"` in your `package.json`.
{% endhint %}

Install and run`tardis-machine` server via `npx` command:

```bash
npx tardis-machine --api-key=YOUR_API_KEY
```

or install globally via `npm`:

```bash
npm install -g tardis-machine
```

and then run:

```bash
tardis-machine --api-key=YOUR_API_KEY
```

Tardis-machine server's HTTP endpoints will be available on port `8000` and WebSocket API endpoints on port `8001`. Your API key will be passed via `--api-key` config flag — simply replace `YOUR_API_KEY` with API key you've received via email.

#### **CLI config flags**

{% hint style="info" %}
You can configure tardis-machine server via [environment variables](#config-environment-variables) as described in Docker section as well.
{% endhint %}

You can set following CLI config flags when starting tardis-machine server installed via `npm`:

| name               | default                     | description                                                                                                                                                                     |
| ------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **--api-key**      |                             | API key for [Tardis.dev](https://tardis.dev/) HTTP API - if not provided only first day of each month of historical data is accessible                                          |
| **--port**         | `8000`                      | HTTP port on which server will be running, **WebSocket port is always this value + 1** (`8001` with port set to `8000`)                                                         |
| **--cache-dir**    | `<os.tmpdir>/.tardis-cache` | path to local dir that will be used as cache location - if not provided default `temp` dir for given OS will be used                                                            |
| **--cluster-mode** | `false`                     | will launch [cluster of Node.js processes](https://nodejs.org/api/cluster.html) to handle the incoming requests if set to `true`, by default server runs in single process mode |
| **--debug**        | `false`                     | server will print verbose debug logs to stdout if set to `true`                                                                                                                 |
| **--clear-cache**  | `false`                     | server will clear local cache dir on startup is set to `true`                                                                                                                   |
| **--help**         |                             | shows CLI help                                                                                                                                                                  |
| **--version**      |                             | shows tardis-machine version number                                                                                                                                             |

## Examples

### Historical normalized replay

{% tabs %}
{% tab title="Python" %}

```python
import asyncio
import aiohttp
import json
import urllib.parse


async def replay_normalized(options):
    encoded_options = urllib.parse.quote_plus(json.dumps(options))
    url = f"http://localhost:8000/replay-normalized?options={encoded_options}"

    async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=0)) as session:
        async with session.get(url) as response:
            async for line in response.content:
                print(json.loads(line))


asyncio.run(
    replay_normalized(
        {
            "exchange": "binance",
            "from": "2024-03-01",
            "to": "2024-03-02",
            "symbols": ["btcusdt"],
            "dataTypes": ["trade", "book_change"],
        }
    )
)
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
import split2 from "split2";
import { Readable } from "stream";

const serialize = (options) => encodeURIComponent(JSON.stringify(options));

async function* replayNormalized(options) {
  const url = `http://localhost:8000/replay-normalized?options=${serialize(options)}`;
  const response = await fetch(url);
  const lines = Readable.fromWeb(response.body).pipe(split2());

  for await (const line of lines) {
    yield JSON.parse(line);
  }
}

const messages = replayNormalized({
  exchange: "binance",
  from: "2024-03-01",
  to: "2024-03-02",
  symbols: ["btcusdt"],
  dataTypes: ["trade", "book_change"],
});

for await (const message of messages) {
  console.log(message);
}
```

{% endtab %}
{% endtabs %}

{% content-ref url="replaying-historical-data" %}
[replaying-historical-data](https://docs.tardis.dev/tardis-machine/replaying-historical-data)
{% endcontent-ref %}

### Real-time normalized streaming

{% tabs %}
{% tab title="Python" %}

```python
import asyncio
import aiohttp
import json
import urllib.parse


async def main():
    stream_options = {
        "exchange": "binance",
        "symbols": ["btcusdt"],
        "dataTypes": ["trade", "book_change"],
    }
    options = urllib.parse.quote_plus(json.dumps(stream_options))
    url = f"ws://localhost:8001/ws-stream-normalized?options={options}"

    async with aiohttp.ClientSession() as session:
        async with session.ws_connect(url) as websocket:
            async for message in websocket:
                print(message.data)


asyncio.run(main())
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
import WebSocket from "ws";

const options = encodeURIComponent(
  JSON.stringify({
    exchange: "binance",
    symbols: ["btcusdt"],
    dataTypes: ["trade", "book_change"],
  }),
);

const ws = new WebSocket(
  `ws://localhost:8001/ws-stream-normalized?options=${options}`,
);

ws.onmessage = (message) => {
  console.log(message.data);
};
```

{% endtab %}
{% endtabs %}

{% content-ref url="streaming-real-time-data" %}
[streaming-real-time-data](https://docs.tardis.dev/tardis-machine/streaming-real-time-data)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tardis.dev/tardis-machine/quickstart.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
