Chistream API
API publik buat integrasi download YouTube/TikTok/Instagram/Facebook ke bot WhatsApp, aplikasi, atau apapun yang kamu buat sendiri. Butuh API key - generate gratis lewat tombol di halaman utama.
Base URL
https://chistream.my.id
Autentikasi
Header: X-API-Key
Rate Limit
5/menit/key (default)
1. Dapetin API Key
Wajib punya akun dulu. Paling gampang lewat daftar/login, terus generate key di dashboard - atau langsung lewat API kayak di bawah. Key cuma ditampilin sekali - simpen baik-baik.
# 1a. Daftar akun (skip kalau udah punya)
curl -X POST https://chistream.my.id/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "namamu", "password": "password_kamu"}'
# 1b. Login buat dapetin token
curl -X POST https://chistream.my.id/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "namamu", "password": "password_kamu"}'
# Balasan: { "success": true, "token": "eyJ...", "user": {...} }
# 1c. Generate API key pakai token dari langkah login
curl -X POST https://chistream.my.id/api/keys/generate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ..." \
-d '{"label": "Bot WhatsApp saya"}'
# Balasan:
# { "success": true, "key": "cs_xxxxxxxxxxxxxxxxxxxxxxxx", "warning": "..." }
Default limit tiap akun baru: 5 request/menit. Butuh lebih? Upgrade plan di billing.
⏳ Key otomatis kadaluarsa 5 hari sejak dibuat - generate key baru lewat dashboard kalau udah lewat.
API Key buat Coba Langsung
Tempel API key kamu di sini sekali - dipakai otomatis sama semua tombol "Jalankan" di dokumentasi ini (biar bisa langsung liat respons ASLI dari server, bukan contoh doang). Cuma disimpen di browser kamu sendiri (localStorage), gak dikirim ke mana-mana selain ke API Chistream pas kamu klik Jalankan.
2. Endpoint yang Tersedia
/api/v1/download
Bikin job download baru. Body JSON: url (link video), format (contoh: mp3, mp4_360p, mp4_720p). Balikin jobId buat dicek statusnya.
/api/v1/status/:jobId
Cek progress/status job. Poll tiap beberapa detik sampai status jadi COMPLETED (ambil downloadUrl) atau FAILED/CANCELLED.
/api/v1/search?q=...
Cari video YouTube berdasarkan kata kunci (5 hasil teratas).
⚠️ File hasil download otomatis terhapus dari server 10 menit setelah selesai diproses (Burn After Download), jadi ambil filenya secepatnya.
Donghua (donghub.vip)
/api/donghua/home?page=1
TANPA BATAS
Daftar update Donghua terbaru dari beranda, dengan pagination.
/api/donghua/search?q=...
TANPA BATAS
Cari judul Donghua berdasarkan kata kunci.
/api/donghua/detail?url=...
TANPA BATAS
Info lengkap + daftar episode dari 1 judul Donghua (pakai link dari hasil search/home).
/api/donghua/stream?url=...
TANPA BATAS
Ambil link stream/embed mentah dari 1 episode (pakai link episode dari detail). Cuma link, bukan file.
/api/donghua/download
KENA KUOTA TIER
Body JSON: url (link episode). Beda sama /stream - ini ngasih FILE beneran (lewat sistem job yang sama kayak /api/v1/download). Kuota per bulan: Free 1x, Basic 10x, Pro 100x - reset tiap 30 hari.
/api/donghua/quota
Cek sisa kuota download-file Donghua bulan ini buat akun kamu.
Coba Langsung (Live)
Isi API key di kotak biru di atas, terus klik Jalankan - request beneran dikirim ke server Chistream dan respons aslinya muncul di bawah. Cuma field API key yang bisa diganti; URL/parameter lainnya udah dikunci ke contoh yang aman biar gak disalahgunakan.
Jalankan dulu contoh "bikin job download" di atas buat isi {jobId}-nya otomatis.
3. Contoh Alur Lengkap (Download → Cek Status)
# 1. Bikin job download
curl -X POST https://chistream.my.id/api/v1/download \
-H "X-API-Key: cs_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"url": "https://youtu.be/VIDEO_ID", "format": "mp3"}'
# Balasan: { "success": true, "jobId": "abc-123", "title": "..." }
# 2. Poll status pakai jobId di atas (ulangi tiap 2-3 detik)
curl https://chistream.my.id/api/v1/status/abc-123 \
-H "X-API-Key: cs_xxxxxxxxxxxxxxxxxxxxxxxx"
# Kalau status COMPLETED, ambil field "downloadUrl" dari balasannya
const API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
const BASE_URL = 'https://chistream.my.id';
async function downloadFromChistream(url, format = 'mp3') {
// 1. Bikin job download
const startRes = await fetch(`${BASE_URL}/api/v1/download`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY,
},
body: JSON.stringify({ url, format }),
});
const startData = await startRes.json();
if (!startData.success) throw new Error(startData.error);
const jobId = startData.jobId;
// 2. Poll sampai selesai
while (true) {
await new Promise((r) => setTimeout(r, 2000));
const statusRes = await fetch(`${BASE_URL}/api/v1/status/${jobId}`, {
headers: { 'X-API-Key': API_KEY },
});
const statusData = await statusRes.json();
if (statusData.status === 'COMPLETED') return statusData;
if (statusData.status === 'FAILED' || statusData.status === 'CANCELLED') {
throw new Error(statusData.error || 'Download gagal');
}
}
}
downloadFromChistream('https://youtu.be/VIDEO_ID', 'mp3')
.then((r) => console.log('Selesai:', r.downloadUrl))
.catch((e) => console.error('Error:', e.message));
const axios = require('axios');
const API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
const BASE_URL = 'https://chistream.my.id';
const headers = { 'X-API-Key': API_KEY };
async function downloadFromChistream(url, format = 'mp3') {
const { data: start } = await axios.post(
`${BASE_URL}/api/v1/download`,
{ url, format },
{ headers }
);
if (!start.success) throw new Error(start.error);
let result;
while (true) {
await new Promise((r) => setTimeout(r, 2000));
const { data: status } = await axios.get(
`${BASE_URL}/api/v1/status/${start.jobId}`,
{ headers }
);
if (status.status === 'COMPLETED') { result = status; break; }
if (status.status === 'FAILED' || status.status === 'CANCELLED') {
throw new Error(status.error || 'Download gagal');
}
}
return result;
}
downloadFromChistream('https://youtu.be/VIDEO_ID', 'mp3')
.then((r) => console.log('Selesai:', r.downloadUrl))
.catch((e) => console.error('Error:', e.message));
import requests
import time
API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx'
BASE_URL = 'https://chistream.my.id'
headers = {'X-API-Key': API_KEY}
def download_from_chistream(url, fmt='mp3'):
start = requests.post(
f'{BASE_URL}/api/v1/download',
json={'url': url, 'format': fmt},
headers=headers,
).json()
if not start.get('success'):
raise Exception(start.get('error'))
job_id = start['jobId']
while True:
time.sleep(2)
status = requests.get(
f'{BASE_URL}/api/v1/status/{job_id}', headers=headers
).json()
if status['status'] == 'COMPLETED':
return status
if status['status'] in ('FAILED', 'CANCELLED'):
raise Exception(status.get('error', 'Download gagal'))
result = download_from_chistream('https://youtu.be/VIDEO_ID', 'mp3')
print('Selesai:', result['downloadUrl'])
<?php
$apiKey = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
$baseUrl = 'https://chistream.my.id';
function chistreamRequest($method, $path, $apiKey, $body = null) {
$ch = curl_init("https://chistream.my.id{$path}");
$headers = ["X-API-Key: {$apiKey}"];
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
}
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
return json_decode($res, true);
}
$start = chistreamRequest('POST', '/api/v1/download', $apiKey, [
'url' => 'https://youtu.be/VIDEO_ID',
'format' => 'mp3',
]);
if (!$start['success']) {
die('Error: ' . $start['error']);
}
$jobId = $start['jobId'];
while (true) {
sleep(2);
$status = chistreamRequest('GET', "/api/v1/status/{$jobId}", $apiKey);
if ($status['status'] === 'COMPLETED') {
echo 'Selesai: ' . $status['downloadUrl'];
break;
}
if (in_array($status['status'], ['FAILED', 'CANCELLED'])) {
die('Download gagal: ' . ($status['error'] ?? ''));
}
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
const apiKey = "cs_xxxxxxxxxxxxxxxxxxxxxxxx"
const baseURL = "https://chistream.my.id"
func chistreamRequest(method, path string, body any) map[string]any {
var reqBody io.Reader
if body != nil {
b, _ := json.Marshal(body)
reqBody = bytes.NewReader(b)
}
req, _ := http.NewRequest(method, baseURL+path, reqBody)
req.Header.Set("X-API-Key", apiKey)
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var out map[string]any
json.NewDecoder(resp.Body).Decode(&out)
return out
}
func main() {
start := chistreamRequest("POST", "/api/v1/download", map[string]string{
"url": "https://youtu.be/VIDEO_ID",
"format": "mp3",
})
if start["success"] != true {
panic(start["error"])
}
jobID := start["jobId"].(string)
for {
time.Sleep(2 * time.Second)
status := chistreamRequest("GET", "/api/v1/status/"+jobID, nil)
switch status["status"] {
case "COMPLETED":
fmt.Println("Selesai:", status["downloadUrl"])
return
case "FAILED", "CANCELLED":
panic(status["error"])
}
}
}
4. Kode Error
| Status | Arti |
|---|---|
| 401 | API key gak ada / gak valid / dinonaktifin. |
| 400 | Body/parameter request gak lengkap (misal url kosong). |
| 404 | jobId gak ditemukan. |
| 429 | Kelewat 5 request/menit buat key ini - tunggu bentar. |
| 500 | Error internal server (link salah, video private, dll). |
5. Catatan
- Format yang didukung:
mp3,opus,wav,flac(audio),mp4_144ps/dmp4_4k(video). - Platform yang didukung: YouTube, TikTok, Instagram, Facebook.
- Jangan share API key kamu ke orang lain - satu key jatahnya cuma 5 request/menit, dipakai bareng-bareng bakal cepet abis.
- Key ilang/bocor? Generate baru aja lewat halaman utama, key lama bisa diminta dinonaktifin.