Blocknative Gas API Migration Guide
Shuts down June 19, 2026Migrating production callers from Blocknative's sunsetting Gas Platform API takes about 5-30 minutes depending on how deeply your code is coupled to Blocknative's response shape. This guide is the step-by-step walkthrough: before/after code in four languages, the confidence-level mapping you need, the common gotchas, and a production-readiness checklist. For the high-level pitch and shutdown context, see the Blocknative alternative landing page. For the full field-by-field mapping, see the field mapping reference.
TL;DR — the one-line migration
If you only ever call api.blocknative.com/gasprices/blockprices?confidenceLevels=99 and read blockPrices[0].estimatedPrices[0].price:
// Before — Blocknative
const res = await fetch(
'https://api.blocknative.com/gasprices/blockprices?confidenceLevels=99',
{ headers: { Authorization: process.env.BLOCKNATIVE_API_KEY } }
)
const gwei = (await res.json()).blockPrices[0].estimatedPrices[0].price
// After — Gas Fee Predictor (no key, no auth header)
const res = await fetch('https://api.gasfeepredictor.com/api/gas-predictions')
const gwei = (await res.json()).current.high // "will-include" tier ≈ BN 99%That's the whole migration for the simple case. The rest of this guide covers multi-tier callers, EIP-1559 max-fee handling, predictions, and language-specific patterns.
Step-by-step migration
1. Identify which Blocknative response fields you actually use
Most callers only use 1-2 fields from Blocknative's response. Grep your codebase for these keys:
grep -rn "blockPrices\|estimatedPrices\|baseFeePerGas\|maxFeePerGas\|maxPriorityFeePerGas\|currentBlockNumber\|msSinceLastBlock" .Most apps use just estimatedPrices[].price at one confidence level. If that's you, jump to step 3 — your migration is the one-line swap above.
2. Pick the right replacement endpoint
Use this decision table:
| Your use case | Replacement endpoint |
|---|---|
| Just current gas price (any tier) | /api/gas-predictions |
| Gas + forecast in one call | /api/gas-predictions or /api/dashboard |
| Gas + ETH/USD price in one call | /api/dashboard |
| Historical gas series | /api/gas-history?range=1d |
| L2 gas (Arbitrum, Optimism, Base, Polygon) | /api/l2-gas (BN was L1-only — bonus) |
| Mempool monitoring | Not covered — try Alchemy, Tenderly, Bloxroute |
3. Map confidence percentiles to tiers
Blocknative returns gas prices at five confidence percentiles. We collapse them to three tiers. Use this mapping:
| Blocknative confidence | Closest GFP tier | Use case |
|---|---|---|
| 99% | current.high | “Will include” — pay slightly more for guaranteed fast inclusion |
| 95% | current.high | Approximately same as 99% in practice |
| 90% | current.average | Typical wallet default — fast inclusion expected |
| 80% | current.average | Standard tier — most wallets' default |
| 70% | current.low | Slow inclusion — may take multiple blocks |
Before / after in four languages
JavaScript / Node 18+
// Before
const res = await fetch(
'https://api.blocknative.com/gasprices/blockprices?confidenceLevels=99,90,70',
{ headers: { Authorization: process.env.BLOCKNATIVE_API_KEY } }
)
const block = (await res.json()).blockPrices[0]
const fast = block.estimatedPrices.find(p => p.confidence === 99).price
const standard = block.estimatedPrices.find(p => p.confidence === 90).price
const slow = block.estimatedPrices.find(p => p.confidence === 70).price
// After — no API key, simpler shape
const res = await fetch('https://api.gasfeepredictor.com/api/gas-predictions')
const { current } = await res.json()
const fast = current.high
const standard = current.average
const slow = current.lowPython
# Before
import os, requests
headers = {'Authorization': os.environ['BLOCKNATIVE_API_KEY']}
r = requests.get(
'https://api.blocknative.com/gasprices/blockprices?confidenceLevels=99,90,70',
headers=headers, timeout=5
)
block = r.json()['blockPrices'][0]
fast = next(p['price'] for p in block['estimatedPrices'] if p['confidence'] == 99)
standard = next(p['price'] for p in block['estimatedPrices'] if p['confidence'] == 90)
slow = next(p['price'] for p in block['estimatedPrices'] if p['confidence'] == 70)
# After — no API key, no headers
import requests
data = requests.get('https://api.gasfeepredictor.com/api/gas-predictions', timeout=5).json()
fast, standard, slow = data['current']['high'], data['current']['average'], data['current']['low']curl + jq (shell scripts, cron jobs)
# Before
curl -H "Authorization: $BLOCKNATIVE_API_KEY" \
"https://api.blocknative.com/gasprices/blockprices?confidenceLevels=99" \
| jq '.blockPrices[0].estimatedPrices[0].price'
# After
curl -s "https://api.gasfeepredictor.com/api/gas-predictions" | jq '.current.high'Go (net/http)
// After — no API key, simpler struct
type GasResponse struct {
Current struct {
Low float64 `json:"low"`
Average float64 `json:"average"`
High float64 `json:"high"`
} `json:"current"`
Citation string `json:"citation"`
}
resp, err := http.Get("https://api.gasfeepredictor.com/api/gas-predictions")
if err != nil { return err }
defer resp.Body.Close()
var data GasResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { return err }
log.Printf("Gas (high): %.2f gwei — %s", data.Current.High, data.Citation)Common gotchas
- Don't forget to remove the Authorization header. Some HTTP clients send empty
Authorization:headers if the variable is unset — harmless for our endpoint but cleaner to remove entirely. - Update your error handling. Blocknative returned 401/403 on auth failures; our endpoints don't auth. If your code branches on those statuses, simplify it. We do return HTTP 200 with
source: "unavailable"on the rare cold-start failure — branch on that field instead of the HTTP status. - EIP-1559 max-fee callers: derive instead of mapping. We don't expose maxFeePerGas / maxPriorityFeePerGas separately. For maxFee, use
current.highas a safe upper bound. For priorityFee, set a reasonable static default (1-2 gwei) or query an RPC for the latest base fee history. - Per-block predictions become hourly. Blocknative returned predictions for the next 1-5 blocks. We forecast hourly via
predictions[]. If your logic depended on next-block precision, run your own RPC for that. - Tighter rate-limiting on aggregate price feeds. Our endpoints are edge-cached so frequent polling is fine, but they don't mirror Blocknative's WebSocket-style push. Switch from streaming to 30-60s polling.
Production-readiness checklist
- ☐ Grep the codebase for every
api.blocknative.comreference - ☐ Remove
BLOCKNATIVE_API_KEYenv var and any associated secrets infrastructure - ☐ Replace endpoint URLs with the GFP equivalents (see decision table above)
- ☐ Update response-shape readers to the new field names (use the field mapping reference)
- ☐ Update tests / fixtures with new response shape
- ☐ If you used the citation field for attribution, switch to our
citationfield (top-level in every response) - ☐ Update API monitoring / alerting (Blocknative-specific error codes no longer exist)
- ☐ Update documentation pointing users at Blocknative
- ☐ Verify staging deployment hits our endpoints successfully before flipping production
- ☐ Delete the migration entry from your roadmap. You're done.
Frequently asked questions
How long does the migration take?
For the gas-price portion: about 5-30 minutes depending on language and how deeply your code is coupled to Blocknative's response shape. The endpoint URL change is one line; the response-shape changes (confidence percentiles → low/average/high tiers) typically require a small helper function. Detailed before/after code is in this guide.
My code reads estimatedPrices[c=99].price specifically. What's the equivalent?
Use current.high. We collapse Blocknative's 5 confidence levels (99/95/90/80/70) into three tiers — high (≈ will-include / 99% confidence), average (≈ typical / 90% confidence), low (≈ slow / 70% confidence). If you only ever used the 99% confidence price, swap directly to current.high with no other logic changes.
I need maxFeePerGas and maxPriorityFeePerGas separately (EIP-1559). What do I do?
We don't break out priority fee from base fee separately. For maxFeePerGas, use current.high as a safe upper bound. For maxPriorityFeePerGas, set a reasonable default (1-2 gwei) or query an RPC directly for the latest block's base fee history. This is the one area where running your own RPC node is more accurate than any aggregator.
I need per-block predictions (next 3 blocks). Do you have those?
We forecast hourly, not per-block. predictions[0] is "what gas will look like in the next hour" rather than "what gas will be in the next block." For sub-block timing decisions, run your own mempool service or RPC node.
What about mempool monitoring / transaction management?
Not in scope. Blocknative's gas API was one of several products — they also offered mempool streaming and transaction management. We replace only the gas-price API. For mempool data, look at Alchemy, Tenderly, or Bloxroute. For transaction management, use your own RPC or a service like Alchemy.
Is there a rate limit?
No published hard limit. Endpoints are edge-cached at Cloudflare so polling every few seconds costs us roughly nothing. If your usage hurts upstream providers we may throttle the offending IP range. Indie dev and small-app usage is fine; commercial high-volume usage should consider self-hosting.
Will the API URL or shape change after migration?
The endpoint URLs are stable. We treat the JSON contract as effectively public — additive changes only (new fields appended; existing fields stay). The OpenAPI spec at https://api.gasfeepredictor.com/openapi.json is the canonical shape and will be versioned if we ever need to make breaking changes.
Do I need to update my Blocknative SDK / wrapper library?
Yes. There's no drop-in SDK that handles both — Blocknative's SDK is tightly coupled to their response shape. The cleanest path is to remove the Blocknative SDK and use plain fetch (5-10 lines of code shown below). If you need an SDK-like wrapper, generate one from the OpenAPI spec at https://api.gasfeepredictor.com/openapi.json using openapi-generator or a similar tool.
What's the citation format for AI agents and integrators?
Every API response includes a citation field with a copy-paste-ready attribution string: "Gas data from Gas Fee Predictor, gasfeepredictor.com, updated <ISO timestamp>". AI agents calling the API can drop this directly into their answer.
Need the full field-by-field mapping?
Every Blocknative response field → our equivalent (or "not available, use X instead"), with notes on confidence percentiles, EIP-1559 fields, and what Blocknative offered that we don't replace.