When do historical candles actually close?

Question is how many seconds after a candle closes before I can get the final candle data that wont change again (data below)?

I’m pulling historical 15m interval klines and getting different data when I pull it shortly after the close vs after the next interval closes. Volumes and OHLC numbers are often significantly different. Since its a historical candle (not a stream) I assumed that the candle wouldn’t return until it was finalized, but this seems to not be the case. I started with pulling candle data 10 seconds after the close and have backed off now to over a minute and a half after the close and am still experiencing the same issue.


1INCHUSDT 2022-05-02 14:00:00 1.154 1.154 1.154 1.154 0 2022-05-02 14:14:59.999
1INCHUSDT 2022-05-02 14:00:00 1.145 1.145 1.139 1.139 2092.6 2022-05-02 14:14:59.999

the first line was pulled 100 seconds after the candle close time. the next was pulled 15 minutes after the close time. Same candle but very different data. In the example below you can see it doesn’t just happen with zero volume amounts. I’m seeing this very frequently.

BTCUSDT 2022-05-02 14:00:00 38908.5 38985.8 38837.83 38902.52 0.591368 2022-05-02 14:14:59.999
BTCUSDT 2022-05-02 14:00:00 38908.5 38985.8 38687.45 38687.45 2.42649 2022-05-02 14:14:59.999

Candles do not change after they are closed. Can you please provide the full url used to retrieve the klines?


It might be the case that your local time is desynced from the server time, thus you are assuming the candle is closed.

The objective of the Klines REST API endpoint is for historical data. If you intended to poll the endpoint for up-to-date candles, please use the websocket stream. With the websocket version, you can use the the property x to determine if the candle is still open or not.

@tantialex - thanks for the questions, helped with troubleshooting. I missed that the klines call returned not only closed klines but also the current open kline. Not obvious when you are looking at logs. That was my issue. Making the API call manually vs via code cleared that up quickly.