🐍 Ngày 62 - Python hằng ngày 365 ngày - Top API miễn phí cho lập trình viên Python

Chủ đề hôm nay đưa bạn đến với 4 API công khai hoàn toàn miễn phí, không cần đăng ký tài khoản hay tạo API key: CoinGecko, Binance, Open Notify và CoinDesk. Chỉ với thư viện chuẩn urllib của Python, bạn sẽ học cách lấy giá tiền mã hóa, dữ liệu nến giao dịch, vị trí trạm vũ trụ quốc tế ISS và giá Bitcoin tổng hợp — mở ra cánh cửa xây dựng các ứng dụng dữ liệu thực tế.
🧠 1. API là gì và vì sao lập trình viên Python nên biết?
Khái niệm cơ bản về API
API (Application Programming Interface) là cầu nối trung gian giúp phần mềm này nói chuyện với phần mềm khác. Thay vì phải tự gõ số liệu hay tự viết thuật toán phức tạp, bạn chỉ cần gửi một yêu cầu tới máy chủ và nhận về dữ liệu đã được xử lý sẵn — thường ở định dạng JSON.
Hãy tưởng tượng API như người phục vụ trong nhà hàng:
- Chương trình của bạn (thực khách) đưa ra yêu cầu (gọi món).
- API (người phục vụ) chuyển yêu cầu vào hệ thống (nhà bếp).
- Hệ thống xử lý xong, API mang kết quả (món ăn) trả về.
- Bạn không cần quan tâm bên trong hoạt động ra sao — chỉ cần nhận đúng thứ mình cần.
Vì sao kỹ năng gọi API quan trọng?
Đối với một lập trình viên Python, biết gọi API mang lại rất nhiều lợi ích thiết thực:
- Lấy dữ liệu thật: giá coin, thời tiết, tin tức, vị trí vệ tinh… mà không cần tự thu thập.
- Tự động hóa công việc: bot gửi email, bot cảnh báo giá, bot đặt lệnh demo đều dựa trên dữ liệu từ API.
- Tiết kiệm thời gian: không phải tự viết bộ phân tích dữ liệu hay duy trì máy chủ riêng.
- Kết nối hệ sinh thái: thanh toán, đăng bài, gửi tin nhắn, quản lý kho… hầu như mọi dịch vụ hiện đại đều có API.
API key là gì? Khi nào cần dùng?
API key giống như chìa khóa phòng — một chuỗi ký tự bí mật giúp máy chủ nhận diện bạn. Máy chủ dùng key để:
- Đếm lượt sử dụng — mỗi key có hạn mức riêng.
- Chặn lạm dụng — ai gọi quá nhiều sẽ bị giới hạn.
- Tính phí — khi vượt quá gói miễn phí.
Tuy nhiên, 4 API trong bài học hôm nay đều là public API: dữ liệu công khai, không nhạy cảm, không cần định danh. Đây là nhóm tốt nhất để bắt đầu vì không vướng thủ tục đăng ký, không lo lộ key, không sợ tốn phí khi thử nghiệm.
Khi nào bạn cần key? Khi gọi API liên quan đến dữ liệu cá nhân (email, tài khoản, lệnh giao dịch) hoặc dịch vụ trả phí (AI, SMS, thanh toán). Lúc đó, nguyên tắc số một là: giữ key trong biến môi trường, không bao giờ hardcode vào code — vì nếu đẩy code lên GitHub công khai, key của bạn sẽ bị quét và bị lạm dụng ngay lập tức.
💡 Nguyên tắc của chuỗi Python 365: 1 ngày = 1 kỹ năng nhỏ dùng được ngay. Hôm nay sau khoảng 15 phút bạn sẽ có 4 API sẵn sàng chạy.
⚙️ 2. Cách gọi API bằng Python — urllib cơ bản
Làm quen với JSON — ngôn ngữ chung của API
JSON (JavaScript Object Notation) là định dạng dữ liệu phổ biến nhất mà các API trả về. Điều may mắn là JSON gần như đồng nhất với dict/list của Python, nên việc chuyển đổi cực kỳ dễ dàng.
Bảng quy đổi JSON ↔ Python:
| JSON | Python |
|---|---|
{} (object) | dict |
[] (array) | list |
"text" (string) | str |
123 / 12.5 (number) | int / float |
true / false | True / False |
null | None |
Khi gặp một API mới, quy trình khám phá thường là:
- In toàn bộ JSON ra (pretty print) để xem cấu trúc.
- Xác định phần dữ liệu mình cần nằm ở đâu trong cây JSON.
- Viết hàm trích xuất đúng phần đó.
- Xử lý trường hợp thiếu key bằng
.get().
import json
data = fetch_json("https://api.coindesk.com/v1/bpi/currentprice.json")
print(json.dumps(data, indent=2, ensure_ascii=False))
Kỹ năng này cực kỳ quan trọng trong thực tế: khi một API thay đổi định dạng, bạn phải đọc lại JSON để biết key mới nằm ở đâu — chứ không phải đoán mò.
Gửi yêu cầu HTTP bằng urllib
Python có sẵn thư viện urllib.request để gửi yêu cầu HTTP — không cần cài đặt thêm bất cứ thứ gì (khác với thư viện requests phổ biến nhưng phải pip install).
Ví dụ đơn giản nhất — gọi API lấy vị trí trạm vũ trụ ISS:
import json
import urllib.request
url = "http://api.open-notify.org/iss-now.json"
with urllib.request.urlopen(url, timeout=15) as resp:
data = json.loads(resp.read().decode("utf-8"))
print(data)
Kết quả sẽ là một dict JSON:
{
"message": "success",
"iss_position": {"latitude": "42.2", "longitude": "-87.4"},
"timestamp": 1755878400
}
Có 3 bước quan trọng:
urllib.request.urlopen(url, timeout=15)— mở kết nối tới URL, giới hạn 15 giây để tránh treo vô hạn nếu mạng chậm.resp.read().decode("utf-8")— đọc toàn bộ nội dung trả về (bytes) rồi giải mã sang chuỗi UTF-8. Nếu quên decode sẽ rab'{"message":...}'— không dùng được.json.loads(...)— chuyển chuỗi JSON thành dict Python để xử lý bình thường.
⚠️ Vì sao phải
decode("utf-8")? Nội dung từ API là dạngbytes(dãy số nhị phân). Hầu hết API trả về UTF-8, nhất là các API có dữ liệu tiếng Việt. Nếu quên decode,json.loadssẽ báo lỗiTypeError: the JSON object must be str, bytes or bytearray.
User-Agent — lời chào quan trọng
Một chi tiết nhỏ nhưng quan trọng: User-Agent. Một số API (đặc biệt là Binance) từ chối yêu cầu từ các thư viện mặc định. Bạn nên kèm một User-Agent mô tả mình là ai:
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PythonDay62"}
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.loads(resp.read().decode("utf-8"))
Việc kèm User-Agent giống như gõ cửa và xưng danh — máy chủ biết ai đang gọi, dễ dàng chấp nhận yêu cầu hơn.
🔧 3. Hàm fetch_json dùng chung cho mọi API
Thay vì lặp lại 3 bước (mở kết nối → decode → json.loads) cho từng API, ta gói gọn vào một hàm dùng chung. Đây là kỹ năng refactor quan trọng: khi có nhiều chỗ cùng một logic, hãy đưa vào một hàm.
import json
import urllib.request
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PythonDay62"}
TIMEOUT = 15
def fetch_json(url: str) -> dict:
"""Hàm dùng chung: GET url -> dict JSON (kèm User-Agent)."""
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
return json.loads(resp.read().decode("utf-8"))
Hàm này nhận một URL, trả về dict JSON. Cả 4 API trong bài hôm nay đều gọi qua đúng một hàm này:
coin_gecko(...)→ gọifetch_json(...)binance_price(...)→ gọifetch_json(...)iss_position(...)→ gọifetch_json(...)coindesk_bpi(...)→ gọifetch_json(...)
Lợi ích:
- Ít code trùng lặp — nếu cần đổi User-Agent, chỉ sửa một chỗ.
- Nhất quán — mọi API đều có timeout 15s, đều kèm User-Agent.
- Dễ bảo trì — thêm API mới chỉ cần viết thêm một hàm nhỏ.
💡 Đây là pattern cực kỳ phổ biến trong dự án thực tế: một hàm client dùng chung ở tầng dưới, các hàm nghiệp vụ ở tầng trên. Các thư viện lớn như
requeststhậm chí còn córequests.Session()để tái sử dụng kết nối — nhưng với bài học hôm nay,fetch_jsonlà đủ.
🪙 4. CoinGecko — lấy giá coin
Giới thiệu
CoinGecko là một trong những API dữ liệu tiền mã hóa miễn phí phổ biến nhất. Không cần API key cho bản dùng thử, endpoint đơn giản, dữ liệu phong phú.
Endpoint sử dụng:
https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true
Phân tích URL:
ids=bitcoin— đồng coin muốn lấy giá (có thể gửi nhiều đồng, cách nhau dấu phẩy:bitcoin,ethereum).vs_currencies=usd— quy đổi sang USD.include_24hr_change=true— kèm thay đổi giá trong 24h.
Hàm Python
def coin_gecko(coin: str = "bitcoin") -> dict:
data = fetch_json(f"https://api.coingecko.com/api/v3/simple/price?"
f"ids={coin}&vs_currencies=usd&include_24hr_change=true")
return data.get(coin, {})
Kết quả trả về:
{
"bitcoin": {
"usd": 61234.5,
"usd_24h_change": 2.14
}
}
Điểm hay cần lưu ý: dùng data.get(coin, {}) thay vì data[coin]. Nếu API trả về rỗng hoặc thiếu coin, hàm không ném lỗi mà trả về dict rỗng — chương trình chạy tiếp bình thường.
Mẹo nhỏ: CoinGecko có rất nhiều endpoint hữu ích khác:
https://api.coingecko.com/api/v3/coins/list— danh sách toàn bộ coin.https://api.coingecko.com/api/v3/coins/{id}/market_chart?vs_currency=usd&days=30— lịch sử giá 30 ngày.https://api.coingecko.com/api/v3/coins/{id}?localization=false— thông tin chi tiết một đồng.
Điều này có nghĩa: từ một bài học nhỏ hôm nay, bạn đã mở ra khả năng xây dựng cả một dashboard giá coin.
Ví dụ nâng cao: lấy giá nhiều đồng cùng lúc
Một trong những sức mạnh của CoinGecko là gọi nhiều đồng trong một lần. Thay vì gọi 5 lần cho 5 đồng, bạn chỉ gọi 1 lần:
def coin_gecko_multi(coins: list[str]) -> dict:
ids = ",".join(coins)
data = fetch_json(
f"https://api.coingecko.com/api/v3/simple/price?"
f"ids={ids}&vs_currencies=usd&include_24hr_change=true"
)
return data
# Dùng:
print(coin_gecko_multi(["bitcoin", "ethereum", "binancecoin"]))
Kết quả:
{
"bitcoin": {"usd": 61234.5, "usd_24h_change": 2.14},
"ethereum": {"usd": 3456.7, "usd_24h_change": 1.08},
"binancecoin": {"usd": 589.2, "usd_24h_change": 0.64}
}
Gọi gộp giúp bạn:
- Giảm số yêu cầu → tránh chạm rate limit.
- Chạy nhanh hơn → 1 lần mạng thay vì 5 lần.
- Code sạch hơn → một dict tổng hợp để xử lý.
Với dữ liệu này, bạn có thể nhanh chóng dựng bảng theo dõi giá:
for coin, info in coin_gecko_multi(["bitcoin", "ethereum", "solana"]).items():
pct = info.get("usd_24h_change", 0)
trend = "🟢" if pct >= 0 else "🔴"
print(f"{trend} {coin:<12} ${info['usd']:>10,.2f} ({pct:+.2f}%)")
Output mẫu:
🟢 bitcoin $61,234.50 (+2.14%)
🔴 ethereum $3,456.70 (-1.08%)
🟢 solana $145.80 (+3.92%)
Đây chính là bước đệm để xây bot cảnh báo giá — chủ đề các ngày sau sẽ đào sâu.
📊 5. Binance public API — giá và nến thật
Giới thiệu
Binance — sàn giao dịch tiền mã hóa lớn nhất thế giới — cung cấp public API hoàn toàn miễn phí, không cần key cho dữ liệu thị trường. Đây là nguồn dữ liệu giá real-time, tần suất cao được hàng triệu bot sử dụng.
Endpoint đơn giản nhất — lấy giá hiện tại:
https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT
Hàm Python
def binance_price(symbol: str = "BTCUSDT") -> dict:
return fetch_json("https://api.binance.com/api/v3/ticker/price?"
f"symbol={symbol}")
Kết quả:
{
"symbol": "BTCUSDT",
"price": "61234.50000000"
}
Lấy dữ liệu nến (klines)
Với các chuỗi bài trước (RSI, MACD, Bollinger, Backtest), bạn đã thấy dữ liệu nến giá từ Binance. Endpoint nến trả về lịch sử giá chi tiết:
https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=5
Kết quả là danh sách các nến, mỗi nến gồm: thời gian mở, giá mở, giá cao, giá thấp, giá đóng, khối lượng…
[
[1755878400000, "61000", "61500", "60800", "61234", "12.5", ...],
[1755882000000, "61234", "61900", "61100", "61800", "15.1", ...]
]
⚠️ Lưu ý về Binance:
- Giá từ Binance trả về dạng chuỗi (string) — cần
float()nếu muốn tính toán.- Klines là danh sách (list) chứ không phải dict — cần truy cập theo chỉ số:
nến[1]là giá mở,nến[4]là giá đóng.- Public API không cần key, nhưng nếu dùng nhiều, cân nhắc giới hạn số yêu cầu (rate limit) để tránh bị chặn IP tạm thời.
Ví dụ nâng cao: gói gọn hàm lấy nến (klines)
Vì các bài sau (backtest, bot demo, arbitrage) đều cần dữ liệu nến, hôm nay ta xây sẵn hàm đọc nến:
def binance_klines(symbol: str = "BTCUSDT",
interval: str = "1h",
limit: int = 100) -> list[dict]:
"""Lấy nến giá từ Binance. Trả về list các dict có key rõ ràng."""
raw = fetch_json(
f"https://api.binance.com/api/v3/klines?"
f"symbol={symbol}&interval={interval}&limit={limit}"
)
candles = []
for k in raw:
candles.append({
"open_time": k[0],
"open": float(k[1]),
"high": float(k[2]),
"low": float(k[3]),
"close": float(k[4]),
"volume": float(k[5]),
})
return candles
# Dùng:
for c in binance_klines(interval="1h", limit=5):
print(f"{c['open_time']} O:{c['open']:.2f} H:{c['high']:.2f} "
f"L:{c['low']:.2f} C:{c['close']:.2f}")
Điểm đáng học:
- Ta biến list "thô" thành list dict có tên rõ ràng — sau này truy cập
c["close"]thay vì nhớk[4]. Đây là cách viết dễ đọc, ít bug. - Hàm này chính là bước đệm cho DataFrame pandas — các ngày về sau sẽ nhét dữ liệu vào pandas để tính RSI, MACD, Bollinger trên chính nguồn dữ liệu này.
💡 Ghi nhớ: với Binance, khi cần real-time giá 1 symbol → dùng
ticker/price. Khi cần lịch sử để phân tích → dùngklines.
Vì sao Binance quan trọng với chuỗi Python 365? Đây chính là nguồn dữ liệu chính cho các bài sau: Bot đặt lệnh demo (Ngày 63), Bot arbitrage (Ngày 67), Bot copy trade (Ngày 70). Hiểu API này hôm nay là nền tảng cho nhiều ngày sắp tới.
🛰️ 6. Open Notify — vị trí trạm vũ trụ ISS
Giới thiệu
Open Notify là API miễn phí tuyệt vời để học — nó trả về vị trí thời gian thực của Trạm Vũ trụ Quốc tế (ISS) đang bay trên bầu trời.
Endpoint:
http://api.open-notify.org/iss-now.json
Hàm Python
def iss_position() -> dict:
data = fetch_json("http://api.open-notify.org/iss-now.json")
pos = data["iss_position"]
return {"lat": float(pos["latitude"]), "lon": float(pos["longitude"]),
"timestamp": data["timestamp"]}
Kết quả:
{
"lat": 42.2,
"lon": -87.4,
"timestamp": 1755878400
}
Điểm đáng chú ý trong code: hàm này làm sạch dữ liệu — lấy chuỗi "42.2" từ API, chuyển thành float(42.2) để sẵn sàng tính toán, và bỏ đi field message không cần thiết. Đây là kỹ năng quan trọng: API trả gì không quan trọng bằng bạn muốn dùng gì.
Ứng dụng thực tế
- Theo dõi ISS bay qua thành phố của bạn khi nào.
- Kết hợp với thư viện vẽ bản đồ để hiển thị quỹ đạo.
- Dạy trẻ em về vũ trụ một cách sinh động.
Open Notify còn có endpoint http://api.open-notify.org/astros.json trả về danh sách phi hành gia đang ở trên trạm — một ví dụ khác để tự khám phá:
def astros_on_iss() -> dict:
data = fetch_json("http://api.open-notify.org/astros.json")
people = [p["name"] for p in data.get("people", [])]
return {"count": data.get("number", 0), "names": people}
print(astros_on_iss())
# {'count': 7, 'names': ['Oleg Kononenko', 'Nikolai Chub', ...]}
💡 Open Notify là ví dụ hoàn hảo cho câu nói: "API biến một thứ tưởng như phức tạp (theo dõi vệ tinh) thành vài dòng code".
Kết hợp: vẽ ISS lên bản đồ ASCII
Thử một bài nhỏ thú vị: dùng vị trí ISS để vẽ lên một bản đồ ASCII — xem vệ tinh đang "bay" qua đâu trên địa cầu:
def draw_iss_map(lat: float, lon: float) -> None:
"""Vẽ bản đồ thế giới đơn giản (kinh độ -180..180, vĩ độ -90..90)."""
W, H = 60, 20
grid = [["."] * W for _ in range(H)]
x = int((lon + 180) / 360 * (W - 1))
y = int((90 - lat) / 180 * (H - 1))
grid[y][x] = "🛰"
for row in grid:
print("".join(row))
pos = iss_position()
draw_iss_map(pos["lat"], pos["lon"])
Đây là ví dụ cho thấy: chỉ cần một API nhỏ + một chút sáng tạo, bạn đã có một chương trình trực quan thú vị — và quan trọng là bạn hiểu toàn bộ luồng: gọi API → xử lý dữ liệu → hiển thị.
💵 7. CoinDesk BPI — giá Bitcoin hôm nay
Giới thiệu
CoinDesk cung cấp API BPI (Bitcoin Price Index) — chỉ số giá Bitcoin được tổng hợp từ nhiều sàn lớn, cập nhật liên tục.
Endpoint:
https://api.coindesk.com/v1/bpi/currentprice.json
Hàm Python
def coindesk_bpi() -> dict:
data = fetch_json("https://api.coindesk.com/v1/bpi/currentprice.json")
usd = data["bpi"]["USD"]
return {"code": usd["code"], "rate": usd["rate_float"],
"updated": data["time"]["updated"]}
Kết quả trả về gọn gàng:
{
"code": "USD",
"rate": 61234.5,
"updated": "Aug 23, 2026 10:00:00 UTC"
}
Điểm thú vị: API gốc trả về rất nhiều thông tin (giá theo nhiều loại tiền tệ: USD, GBP, EUR…). Hàm của chúng ta chỉ trích xuất phần cần thiết — tạo ra một dict gọn, dễ dùng. Đây là cách tổ chức code tốt: hàm nghiệp vụ trả về đúng thứ người dùng cần, không lộ chi tiết API bên dưới.
Nếu bạn muốn chuyển đổi giữa các loại tiền:
def coindesk_bpi_any(code: str = "USD") -> dict:
data = fetch_json("https://api.coindesk.com/v1/bpi/currentprice.json")
item = data["bpi"].get(code)
return {"code": code, "rate": item["rate_float"]}
Bảng so sánh 4 API — nên dùng cái nào khi nào?
| Tiêu chí | CoinGecko | Binance | Open Notify | CoinDesk |
|---|---|---|---|---|
| Cần API key | ❌ Không | ❌ Không | ❌ Không | ❌ Không |
| Nội dung | Giá + info nhiều coin | Giá + nến real-time | Vị trí ISS | Giá BTC tổng hợp |
| Độ trễ | Vài giây | Real-time | Real-time | Vài giây |
| Rate limit | ~5-10 req/phút | Cao (theo IP) | Rất cao | Cao |
| Dùng khi | Dashboard nhiều coin | Bot giao dịch | Học API / vũ trụ | Giá BTC chuẩn chỉ |
Quy tắc chọn nhanh:
- Cần giá nhiều coin cho bảng theo dõi → CoinGecko.
- Cần giá real-time / nến lịch sử cho bot → Binance.
- Muốn học cách gọi API an toàn, vui vẻ → Open Notify.
- Muốn một con số BTC chuẩn từ chỉ số tổng hợp → CoinDesk BPI.
🚀 8. Script Ngày 62 hoàn chỉnh
Kết hợp tất cả lại thành một script chạy được ngay:
# -*- coding: utf-8 -*-
"""
Day 62 - Top API miễn phí cho lập trình viên Python
=====================================================
Demo các API công khai miễn phí (không cần đăng ký):
1. CoinGecko — giá coin + thông tin
2. Binance public — nến giá (klines)
3. Open Notify — vị trí trạm ISS
4. CoinDesk (BPI) — giá Bitcoin hôm nay
Gói gọn trong hàm fetch_json() dùng chung.
"""
import json
import sys
import urllib.request
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PythonDay62"}
TIMEOUT = 15
def fetch_json(url: str) -> dict:
"""Hàm dùng chung: GET url -> dict JSON (kèm User-Agent)."""
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
return json.loads(resp.read().decode("utf-8"))
def coin_gecko(coin: str = "bitcoin") -> dict:
data = fetch_json(f"https://api.coingecko.com/api/v3/simple/price?"
f"ids={coin}&vs_currencies=usd&include_24hr_change=true")
return data.get(coin, {})
def binance_price(symbol: str = "BTCUSDT") -> dict:
return fetch_json("https://api.binance.com/api/v3/ticker/price?"
f"symbol={symbol}")
def iss_position() -> dict:
data = fetch_json("http://api.open-notify.org/iss-now.json")
pos = data["iss_position"]
return {"lat": float(pos["latitude"]), "lon": float(pos["longitude"]),
"timestamp": data["timestamp"]}
def coindesk_bpi() -> dict:
data = fetch_json("https://api.coindesk.com/v1/bpi/currentprice.json")
usd = data["bpi"]["USD"]
return {"code": usd["code"], "rate": usd["rate_float"],
"updated": data["time"]["updated"]}
def main():
print("=" * 56)
print(" TOP API MIỄN PHÍ | Python 365 - Ngày 62")
print("=" * 56)
apis = [
("CoinGecko", coin_gecko, []),
("Binance public", binance_price, []),
("Open Notify ISS", iss_position, []),
("CoinDesk BPI", coindesk_bpi, []),
]
for name, fn, args in apis:
try:
result = fn(*args)
print(f"\n📡 {name}:")
for k, v in result.items():
print(f" {k}: {v}")
except Exception as exc:
print(f"\n⚠️ {name} lỗi: {exc}")
if __name__ == "__main__":
main()
Cách chạy:
python "Day 62_Top API mien phi.py"
Đầu ra mẫu:
========================================================
TOP API MIỄN PHÍ | Python 365 - Ngày 62
========================================================
📡 CoinGecko:
usd: 61234.5
usd_24h_change: 2.14
📡 Binance public:
symbol: BTCUSDT
price: 61234.50000000
📡 Open Notify ISS:
lat: 42.2
lon: -87.4
timestamp: 1755878400
📡 CoinDesk BPI:
code: USD
rate: 61234.5
updated: Aug 23, 2026 10:00:00 UTC
Cấu trúc script rất đáng học:
- Một hàm
fetch_jsonở tầng dưới — tất cả API đều gọi qua. - Bốn hàm nghiệp vụ — mỗi hàm biết cách đọc đúng phần dữ liệu cần.
- Danh sách
apis— dễ thêm API mới: chỉ cần thêm một tuple("Tên", hàm, args). try/exceptquanh từng API — một API lỗi không làm chết toàn bộ chương trình.
🛡️ 9. Xử lý lỗi khi gọi API
Gọi API ngoài mạng không phải lúc nào cũng thành công. Có 3 loại lỗi thường gặp:
9.1. Lỗi mạng (timeout)
import urllib.error
try:
data = fetch_json("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd")
except urllib.error.URLError as e:
print(f"Mạng lỗi hoặc hết thời gian: {e}")
9.2. Lỗi HTTP (máy chủ trả về 4xx / 5xx)
import urllib.error
try:
data = fetch_json("https://api.binance.com/api/v3/ticker/price?symbol=KHM_PHA")
except urllib.error.HTTPError as e:
print(f"HTTP {e.code}: {e.reason}")
404 Not Found— endpoint hoặc symbol sai.429 Too Many Requests— gọi quá nhanh, bị rate limit.5xx— lỗi phía máy chủ, thử lại sau.
9.3. Lỗi dữ liệu (JSON sai hoặc thiếu key)
try:
data = fetch_json("...")
price = data["price"] # KeyError nếu API đổi format
except (KeyError, json.JSONDecodeError) as e:
print(f"Dữ liệu không như mong đợi: {e}")
Mẹo chuyên nghiệp:
- Dùng
data.get("price", 0)thay vìdata["price"]khi giá trị mặc định hợp lý. - Log lỗi thay vì chỉ in — để sau này dò lại.
- Retry có độ trễ — gọi lại sau 1-2 giây khi gặp lỗi tạm thời.
Ví dụ: hàm fetch_json có retry tự động
Vì các API miễn phí đôi khi bận (rate limit, máy chủ quá tải), một hàm fetch_json có retry sẽ giúp chương trình bền bỉ hơn rất nhiều:
import time
def fetch_json_retry(url: str, tries: int = 3, delay: float = 2.0) -> dict:
"""Gọi API, thử lại khi gặp lỗi tạm thời."""
for attempt in range(tries):
try:
return fetch_json(url)
except Exception as e:
if attempt == tries - 1:
raise
print(f"⚠️ Lỗi (thử {attempt + 1}/{tries}): {e}. Thử lại sau {delay}s...")
time.sleep(delay)
return {} # không bao giờ tới — để cho type checker vui
# Dùng — gọi 1 lần nhưng tự động retry khi lỗi:
btc = fetch_json_retry(
"https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT"
)
print(btc)
Lưu ý: chỉ retry với lỗi tạm thời. Nếu API trả 404 (sai đường dẫn) hoặc 400 (sai tham số), retry vô ích — bạn nên để lỗi hiện ra và sửa code. Nếu là 429 (rate limit) hoặc 5xx (máy chủ bận), retry mới có ý nghĩa.
❓ 10. FAQ
Hỏi: Các API này có thực sự miễn phí không? Có giới hạn không?
Trả lời: Có, cả 4 API đều có gói miễn phí không cần đăng ký. Tuy nhiên đều có giới hạn tần suất (rate limit) — ví dụ CoinGecko giới hạn ~5-10 yêu cầu/phút, Binance cũng có giới hạn. Dùng với tần suất hợp lý là ổn.
Hỏi: Khác gì giữa urllib và requests? Dùng cái nào?
Trả lời: urllib là thư viện chuẩn — không cần cài. requests thân thiện hơn (cú pháp ngắn gọn, tự xử lý JSON bằng resp.json()). Bài này chọn urllib để không phải cài thêm gì. Trong dự án thực tế, requests phổ biến hơn.
Hỏi: Muốn gọi API cần API key thì làm sao?
Trả lời: Nguyên tắc giống hệt — chỉ thêm header Authorization: Bearer <token> (hoặc query param ?api_key=...). Lưu key vào biến môi trường, đừng hardcode trong code.
Hỏi: Vì sao Binance trả giá dạng chuỗi "61234.5" mà không phải số?
Trả lời: Để tránh mất độ chính xác với số thập phân lớn (tương tự lý do dùng Decimal cho tiền tệ). Khi cần tính toán, dùng float() hoặc Decimal().
Hỏi: Tôi muốn xây bot cảnh báo giá — nên dùng API nào?
Trả lời: Với giá real-time tần suất cao, dùng Binance public API. Với thông tin tổng hợp nhiều đồng coin, dùng CoinGecko. Cả hai đều miễn phí cho nhu cầu cá nhân.
Hỏi: Gọi API bị chặn IP thì phải làm sao?
Trả lời: Kiểm tra xem bạn có gọi quá nhanh không (thêm time.sleep(1) giữa các lần gọi). Đọc tài liệu rate limit của từng API. Tránh spam yêu cầu vô nghĩa — máy chủ miễn phí không chịu được tải lớn.
🎯 11. Kết luận
Hôm nay bạn đã học một trong những kỹ năng quan trọng nhất của lập trình viên: gọi API để lấy dữ liệu thật. Cụ thể:
- Cách gọi API bằng
urllib— không cần cài thêm thư viện. - Hàm
fetch_jsondùng chung — gói gọn logic, tái sử dụng cho mọi API. - CoinGecko — giá coin.
- Binance public API — giá và nến thật, nguồn dữ liệu chính cho các bài sau.
- Open Notify — vị trí trạm ISS.
- CoinDesk BPI — giá Bitcoin tổng hợp.
- Xử lý lỗi — mạng, HTTP, dữ liệu.
Từ hôm nay, bạn không còn là người xem dữ liệu — bạn là người gọi dữ liệu. Mọi thứ từ giá coin, thời tiết, tin tức đến vị trí vệ tinh đều trong tầm tay.
Bài tập về nhà
- Chạy script và đối chiếu giá Bitcoin từ 3 nguồn: CoinGecko, Binance, CoinDesk — có khác nhau không? Vì sao?
- Sửa
coin_gecko("ethereum")để lấy giá ETH. - Thêm một API thứ 5 bạn tự tìm (gợi ý: thời tiết OpenWeather miễn phí có key, hoặc API tin tức).
📚 Chuỗi Python 365 ngày: mỗi ngày một kỹ năng nhỏ, dùng được ngay. Xem playlist trên YouTube và theo dõi Hướng Nghiệp Dữ Liệu để không bỏ lỡ bài tiếp theo.
Ngày mai — Ngày 63, chúng ta sẽ dùng chính những API này để dựng Bot đặt lệnh demo bằng Python — mô phỏng giao dịch thử không rủi ro, tự tải giá thật từ Binance, sinh tín hiệu bằng đường trung bình (MA), và báo cáo lãi/lỗi. Đừng bỏ lỡ!