Doji Candlestick Pattern
Category: Candlestick patterns · Updated November 2026
The TAAPI.IO Doji API tells you, candle by candle, whether a candle is a doji: a candle that opens and closes at almost the same price. It works on crypto pairs and US stocks. Send an exchange, symbol and timeframe and get 100 for a doji and 0 for any other candle, with no candles to download and no pattern logic to maintain.
What one request returns
- One value per candle:
100when the candle's body is tiny compared with recent candles,0otherwise. A doji has no direction, so the value is never negative. - The candle's timestamp, so you can match each value to its candle.
- The rule: the body (|close − open|) must be at most 10% of the average high-to-low range of the 10 candles before it.
The default returns the newest candle, which is usually still forming. Add backtrack=1 for the last closed candle, or results to get a series.
Example: BTCUSDT, May to June 2026
Request: BTCUSDT on daily Binance candles with results=300, made on 12 November 2026. In the 40 days charted below, the API flagged 7 dojis. One of them is the textbook case.
| Candle (UTC) | Body | Avg range of previous 10 | Body ÷ avg range | value |
|---|---|---|---|---|
| 6 Jun 2026 | 171.85 | 2,801.57 | 6.1% | 100 |
| 4 Jun 2026 | 256.76 | 2,318.12 | 11.1% | 0 |
| 19 May 2026 | 167.52 | 2,091.43 | 8.0% | 100 |
How to interpret this: Bitcoin fell from 73,461 on 29 May to 59,131 on 5 June. On 6 June it opened at 61,056 and closed at 60,885: a move of 172 on a day that ranged over 2,000. After a 17% fall in eight days, that is sellers running out of steam. On its own it is only indecision. The next day settled it: 7 June closed at 63,332, above the doji's 61,530 high, and price reached 67,292 by 15 June.
The other dojis show why you need that context. 19 May was also a doji in a falling market, and the next day even closed above its high, but the decline carried on a week later. And 4 June looks like a doji on the chart, with a body under 8% of its own range, but the API compares the body with the average range of the previous 10 candles, and at 11.1% it misses the 10% cut.
value is 100. Hollow candles closed higher than they opened, filled ones lower. The green line is the 6 June doji's high; the triangle marks the candle that closed above it. The run of dojis from 8 to 12 June came after the crash had inflated the 10-candle average range, which made small bodies easier to qualify.Why 6 June worked and 19 May didn't
Both were dojis in a falling market, and both were followed by a close above the doji's high. The numbers around them were very different.
| 19 May doji | 6 June doji | |
|---|---|---|
| Change over the 8 days before | −6.0% | −17.1% |
| RSI(14) at the doji's close | 44.5, neutral | 15.5, deeply oversold |
| Close vs EMA(20) | −2.3% | −13.9% |
| Volume into the doji | Light: 8k to 19k BTC a day | Rising every day: 24k up to 55k BTC on 5 June |
| Next close above the doji's high | +138, 0.07 ATR | +1,802, 0.72 ATR |
| Volume on that next candle | 0.78 × 20-day average | 1.41 × 20-day average |
19 May came after a slow drift on light volume. There was no heavy selling for the doji to stop, so it was an ordinary candle in a quiet market. The next close cleared its high by 138 on a day with a typical range near 2,000: technically a confirmation, but really noise.
6 June came right after a selling climax. Volume rose every day into 5 June, which dipped to 59,131 and left a long lower wick. The doji then held above that low on a smaller range, with RSI at 15 and price 14% under its 20-day average. The next day buyers took over clearly, closing well above the doji's high on heavy volume.
Turned into filters on top of value == 100:
- A real move before it: RSI(14) under 30, or the close at least 8% under EMA(20).
- Selling pressure building: volume rising into the doji.
- A clear confirmation: the next close at least 0.5 ATR above the doji's high, not just above it.
19 May fails all three. The 29 May doji (RSI 35) never got a close above its high. Only 6 June passes. That is one example in hindsight; test any filter on many dojis before trusting it.
Example chosen for illustration; many dojis are followed by nothing in particular. Not financial advice.
| Spec | Value |
|---|---|
| Endpoint | GET https://v2.taapi.io/indicator/doji |
| Outputs | value (0 or 100) and timestamp |
| Rule | Body ≤ 10% of the average high−low range of the previous 10 candles |
| Markets | Binance, Binance Futures, Bybit, Gate.io, Kraken and US stocks |
| Timeframes | 1m to 1w |
| Delivery | REST, bulk and WebSocket |
Get Doji with one API call
This request returns Doji for BTCUSDT on 1-hour Binance candles. Add your API key to run it here.
curl -G https://v2.taapi.io/indicator/doji \ -H "Authorization: Bearer YOUR_API_KEY" \ --data-urlencode "exchange=binance" \ --data-urlencode "symbol=BTCUSDT" \ --data-urlencode "timeframe=1h"
import requests
resp = requests.get(
'https://v2.taapi.io/indicator/doji',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'exchange': 'binance', 'symbol': 'BTCUSDT', 'timeframe': '1h'},
)
print(resp.json())const params = new URLSearchParams({"exchange": "binance", "symbol": "BTCUSDT", "timeframe": "1h"});
const res = await fetch(`https://v2.taapi.io/indicator/doji?${params}`, {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
});
console.log(await res.json());Doji API response
The request above with results=10 added, from the live API on 12 November 2026 at 11:17 UTC. The candle at 03:00 UTC (1794452400) was a doji. The last element, 11:00 UTC, was the candle still forming.
{
"value": [0, 100, 0, 0, 0, 0, 0, 0, 0, 0],
"timestamp": [1794448800, 1794452400, 1794456000, 1794459600, 1794463200, 1794466800, 1794470400, 1794474000, 1794477600, 1794481200]
}| Field | Type | Description |
|---|---|---|
value | integer[] | 100 if the candle is a doji, 0 if not. Oldest first |
timestamp | integer[] | Unix time of each candle's open, in seconds, matching the candles endpoint |
Without results you still get arrays, each with one element.
Doji API parameters
Doji has no settings of its own: the 10-candle average and the 10% threshold are fixed.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
exchange | string | Yes | — | binance, binancefutures, bybit, gateio, kraken or stocks |
symbol | string | Yes | — | Pair or ticker, e.g. BTCUSDT or AAPL |
timeframe | string | Yes | — | 1m 5m 15m 1h 4h 1d 1w |
results | integer | No | 1 | Number of values to return, or max |
backtrack | integer | No | 0 | Candles to skip from the most recent. 1 makes the last element the last closed candle |
What is a Doji?
A doji is a single candle whose open and close are almost the same, so the body is a thin line. Buyers and sellers both pushed price around during the candle and ended where they started: the market could not decide. The wicks tell you how far each side got. A doji with a long lower wick is a Dragonfly Doji, with a long upper wick a Gravestone Doji, and with long wicks on both sides a Long Legged Doji. This endpoint flags all of them, since it only looks at the body.
Why it matters
Indecision means something only when it interrupts conviction. After a strong move down, a doji shows the selling pressure has stalled; after a strong move up, the buying. That makes it a possible reversal warning, not a signal on its own. In a sideways market dojis are common and mean very little. Traders usually wait for the next candle: a close above the doji's high after a downtrend, or below its low after an uptrend, before acting.
How the API decides
| Step | Rule |
|---|---|
| Body | |close − open| of the candle |
| Yardstick | Average of (high − low) over the 10 candles before it; the candle itself is not included |
| Doji | Body ≤ 10% of that average → 100, otherwise 0 |
Because the yardstick is the recent average and not the candle's own range, a candle with a small body can miss after a quiet stretch (4 June above), and ordinary-looking candles can qualify right after a volatile one. Wicks don't count at all. We checked the live output against this rule on 1,190 candles across BTC, ETH, SOL, AAPL and SPY on timeframes from 15 minutes to 1 day, with no differences.
How to read Doji in your code
| Signal | Meaning | Condition |
|---|---|---|
| Doji | Open and close almost equal: indecision | value equals 100 |
| No doji | Normal candle | value equals 0 |
| Possible bottom | Indecision after a fall | Doji, and price fell over the candles before it |
| Confirmed | Buyers took over | The next candle closes above the doji's high |
Mind the newest candle. Without backtrack, the last value belongs to the candle that is still forming. Its open is fixed but its close is just the latest price, so a 100 can turn into 0 a minute later, and the other way round. Use backtrack=1 to read only closed candles.
Limitations: Dojis are frequent. In our checks the API flagged 15 to 21% of candles, about one in seven on BTCUSDT 1h, so always add context such as a prior trend, a support level or volume. The pattern looks at one candle at a time and knows nothing about trend. Very short timeframes and quiet hours produce many dojis that mean nothing. Each value needs the 10 candles before it. Nothing on this page is financial advice.
Detect a confirmed Doji with Python
This checks the last two closed candles: was the first a doji, had price fallen before it, and did the second close above its high? backtrack=1 on both requests keeps the forming candle out, and the two responses line up candle for candle.
curl -G https://v2.taapi.io/indicator/doji \ -H "Authorization: Bearer YOUR_API_KEY" \ --data-urlencode "exchange=binance" \ --data-urlencode "symbol=BTCUSDT" \ --data-urlencode "timeframe=1h" \ --data-urlencode "results=2" \ --data-urlencode "backtrack=1"
import requests
API = 'https://v2.taapi.io'
HEADERS = {'Authorization': 'Bearer YOUR_API_KEY'}
market = {'exchange': 'binance', 'symbol': 'BTCUSDT', 'timeframe': '1h', 'backtrack': 1}
# Last 2 closed candles: the possible doji, then the confirmation candle
doji = requests.get(f'{API}/indicator/doji', headers=HEADERS,
params={**market, 'results': 2}).json()
# Last 10 closed candles, oldest first
candles = requests.get(f'{API}/candles', headers=HEADERS,
params={**market, 'results': 10}).json()
doji_candle, next_candle = candles[-2], candles[-1]
is_doji = doji['value'][-2] == 100
fell_before = doji_candle['close'] < candles[0]['close'] * 0.97 # down 3%+ over 8 candles
confirmed = next_candle['close'] > doji_candle['high']
if is_doji and fell_before and confirmed:
print('Doji after a fall, confirmed by a close above its high')
elif is_doji:
print('Doji, but no downtrend or no confirmation yet')
else:
print('No doji on the previous candle')Get historical Doji values
Add results to return a series for backtesting or charting. The last element is the most recent candle. Fetch the same number of candles to draw them: the timestamps match.
curl -G https://v2.taapi.io/indicator/doji \ -H "Authorization: Bearer YOUR_API_KEY" \ --data-urlencode "exchange=binance" \ --data-urlencode "symbol=BTCUSDT" \ --data-urlencode "timeframe=1h" \ --data-urlencode "results=100"
Get Doji for multiple symbols
Combine Doji with other indicators in one request. Each exchange, symbol and timeframe combination is one construct: Basic allows 1 per request, Pro 3 and Expert 10.
curl -X POST https://v2.taapi.io/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"constructs": [
{
"id": "btc_1h",
"exchange": "binance",
"symbol": "BTCUSDT",
"timeframe": "1h",
"indicators": [
{
"id": "doji",
"indicator": "doji"
},
{
"id": "rsi",
"indicator": "rsi"
}
]
}
]
}'Stream Doji in real time
Subscribe over WebSocket to receive new values every 5 seconds while the candle is forming. Streaming supports 1m, 5m, 15m and 1h, and uses interval where REST uses timeframe. Streamed values are for the forming candle, so they can flip until it closes.
{
"type": "subscribe",
"id": "doji",
"exchange": "binance",
"symbol": "BTCUSDT",
"interval": "1m",
"indicator": "doji"
}Doji API FAQ
What does the Doji API return?
Two arrays: value, with 100 for a doji and 0 otherwise, and timestamp, the open time of each candle. Results are JSON.
Can the value be −100?
No. Some other candlestick patterns use −100 for bearish signals, but a doji has no direction, so this endpoint only returns 0 or 100. Decide the direction from the trend before it and the candle after it.
How small does the body have to be?
At most 10% of the average high-to-low range of the previous 10 candles. The threshold is fixed and cannot be changed by a parameter.
Why did a doji disappear?
It was on the candle that was still forming. Until the candle closes its close keeps moving, and so does the result. Add backtrack=1 to check only closed candles.
Can I get Doji for US stocks?
Yes. Use exchange=stocks with a ticker such as AAPL. US stocks are included on the Pro plan and above.
Related indicators
See the full list of indicators, or start for free.