# Download forex and commodity history as CSV

A small Node.js 20+ example that downloads historical OHLCV bars from SiftingIO.
No package installation is needed. It follows cursor pagination and writes a
CSV only after all requested pages have been checked.

## Start here

1. [Create a free SiftingIO account](https://sifting.io/register).
2. Complete account verification and create an API key in your dashboard.
3. [Download export-history.mjs](https://sifting.io/downloads/market-data-csv/export-history.mjs).
4. In the folder containing the file, set `SIFTING_API_KEY` locally. Do not put
   your key in the script, a shared notebook, a repository or a screenshot.

For example, in a Bash or Zsh terminal, enter the key without displaying it:

```sh
printf 'SiftingIO API key: '
read -r -s SIFTING_API_KEY
export SIFTING_API_KEY
printf '\n'
```

## Example: EURUSD hourly bars

```sh
node export-history.mjs \
  --market forex --symbol EURUSD --interval 1h \
  --start 2026-10-05 --end 2026-10-09 \
  --output eurusd-hourly.csv
```

For gold, change `--market` to `commodities` and `--symbol` to `XAUUSD`, and
choose a different output filename. The dates above are examples, not a promise
of coverage. Choose the period you need; availability varies by series and
interval. You can also preview data in the
[CSV and Excel download tool](https://sifting.io/tools/market-data-export).

## What the file contains

| Column                         | Meaning                                                |
| ------------------------------ | ------------------------------------------------------ |
| `timestamp_utc`                | Bar timestamp formatted in UTC                         |
| `timestamp_ms`                 | The same timestamp as Unix milliseconds                |
| `open`, `high`, `low`, `close` | OHLC prices returned by the historical endpoint        |
| `volume`                       | The API's `v` value, unchanged; blank when unavailable |

Do not assume that volume has the same economic meaning across asset classes.
See the [forex](https://sifting.io/docs/historical/forex) and
[commodities](https://sifting.io/docs/historical/commodities) references.
The script does not fill market closures, adjust prices or convert currencies.

## Dates, pagination and safety

- Date-only inputs include the whole UTC day. Explicit UTC timestamps ending in
  `Z` are also accepted. Start and end are inclusive.
- Supported example intervals: `5m`, `15m`, `30m`, `1h`, `1d`.
- Each page requests up to 1,000 bars. The default is at most 10 requests;
  `--max-pages 20` raises that bound, up to a maximum of 100.
- All pages use the same symbol, interval and date range. Only the cursor changes.
- Identical overlapping bars are deduplicated by timestamp; conflicting bars
  stop the export. Rows are ordered oldest first.
- A non-empty continuation cursor means there are more results. Hitting the page
  limit is an error, not a successful partial download. Shorten the period or
  deliberately raise the limit.
- Requests time out after 30 seconds. Redirects are rejected so the API key is
  not forwarded elsewhere. The key is sent in `X-API-Key`, never in the URL.
- Existing files are never overwritten. Failed requests, empty results and
  malformed responses do not produce a CSV. A local disk-write failure is still
  possible; check the command's exit status before using the file.
- `401`/`403`: check the key and market access. `422`: check symbol and available
  dates. `429`: wait before retrying and check your allowance. Requests are
  sequential and are not automatically retried.

This is an educational REST example, not a live WebSocket client or a bulk
dataset service. Historical bars come from REST; live updates use WebSocket.
API allowances and licensing terms still apply. Commercial display and
redistribution rights depend on your plan and agreement:
[Forex API](https://sifting.io/product/forex),
[Commodity Data API](https://sifting.io/product/commodities),
[pricing](https://sifting.io/pricing).
