ML

Melolo API

Melolo is an Indonesian short drama platform powered by ByteDance's Fizzo engine, featuring 821+ drama series. This API provides search, trending, episode streaming with CENC DRM decryption, multi-quality video options, and 16 language support.

Server-Side Decrypt
Just play the hlsUrl — server handles DRM
🔒
CENC AES-128-CTR
4 playback methods — browser or server
📷
Multi-Quality
360p / 480p / 720p / 1080p
🌐
Multi-Language
Hardsub multi-language

Encrypted HLS Playback Guide

DRM

Melolo videos are CENC AES-128-CTR encrypted (DRM protected by ByteDance/Fizzo). The API provides 4 methods to play them — from zero-effort to full DIY.

1
Method 1: Server-Side HLS Easiest
Use the hlsUrl from the episode response. Our server fetches the encrypted MP4 from TikTok CDN, decrypts it with CENC AES-128-CTR, and streams you a clean MP4. Zero client-side DRM code needed.
## Step 1: Get episode data (returns hlsUrl) curl -H "X-API-Key: YOUR_KEY" \ "{{BASE}}/api/melolo/episode?id=7430026544543482113&ep=1&lang=id" ## Step 2: Play the hlsUrl directly (requires API key) curl -H "X-API-Key: YOUR_KEY" \ -o video.mp4 "{{BASE}}/api/melolo/hls?id=7430026544543482113&ep=1&lang=id" ## Or embed in HTML — just a normal <video> tag with api_key query param: <video src="{{BASE}}/api/melolo/hls?id=7430026544543482113&ep=1&api_key=YOUR_KEY" controls></video>
2
Method 2: Client-Side Browser Player Zero Bandwidth
Open the /api/melolo/player URL in a browser. The page fetches the encrypted MP4 directly from TikTok CDN, decrypts it client-side using SubtleCrypto (WebCrypto API), and plays via Blob URL. Our server uses zero bandwidth.
## Open in browser — client-side CENC decrypt player {{BASE}}/api/melolo/player?id=7430026544543482113&ep=1&lang=id ## How it works: ## 1. Browser fetches encrypted MP4 from TikTok CDN (direct) ## 2. Parses ISO BMFF → finds senc per-sample IVs ## 3. Decrypts mdat samples with AES-128-CTR + per-sample IV ## 4. Neutralizes DRM boxes (encv→hvc1, sinf/senc/tenc→free) ## 5. Creates Blob URL → plays in <video> tag
3
Method 3: Service Worker Streaming Progressive
The DRM test player uses a Service Worker that decrypts progressively — video starts playing in ~2s while still downloading. SW intercepts /sw-play requests, streams decrypted MP4.
## Open in browser — Service Worker progressive decrypt {{BASE}}/api/melolo/drm-test/7430026544543482113?ep=1 ## Uses melolo-sw.js Service Worker: ## 1. Registers SW at /melolo-sw.js ## 2. Fetches DRM key via /api/melolo/key?vid={kid} ## 3. Sets video.src = /sw-play?url=CDN_URL&key=KEY_HEX ## 4. SW intercepts → streams decrypt → video plays in ~2s
4
Method 4: DIY with Decrypt Info Advanced
Get the raw CDN URL, AES key, and KID via /api/melolo/decrypt-info, then implement your own CENC decryption. Useful for native apps, ffmpeg pipelines, or custom players.
## Get decryption metadata (all qualities) curl "{{BASE}}/api/melolo/decrypt-info?id=7430026544543482113&ep=1&lang=id" ## Response includes per-quality: ## cdnUrl: encrypted MP4 on TikTok CDN ## contentKey: AES-128 key (hex) for CENC-AES-CTR ## kid: Key ID ## encrypted: true/false ## decryptMethod: "cenc-aes-ctr" ## usage: step-by-step decrypt instructions ## Or get just the AES key for a specific KID: curl "{{BASE}}/api/melolo/key?vid={kid_from_episode}"

Which method should I use?

Method 1 (Server HLS) — Simplest. Just use hlsUrl. Server handles everything.
Method 2 (Client Player) — Best for web apps. Zero server bandwidth, full browser decrypt.
Method 3 (SW Streaming) — Fastest playback start. Progressive decrypt in ~2 seconds.
Method 4 (DIY) — For custom integrations, native apps, ffmpeg pipelines.

JavaScript SDK — melolo-decrypt.js

Client-Side

A standalone JavaScript library for client-side CENC AES-128-CTR decryption using the WebCrypto API. Supports streaming overlap decrypt (decrypts while downloading), pre-allocated buffers, and parallel sample processing.

1
Include the Script
<script src="{{BASE}}/melolo-decrypt.js"></script>
2
Quick Play (recommended)
The MeloloDecrypt.play() method handles everything: fetches episode data, gets the DRM key, downloads + decrypts the encrypted MP4, and plays it.
<video id="player" controls></video> <script src="{{BASE}}/melolo-decrypt.js"></script> <script> MeloloDecrypt.play(document.getElementById('player'), { apiBase: '{{BASE}}', bookId: '7430026544543482113', episode: 1, quality: '720p', // optional: 360p/480p/720p/1080p onProgress: (phase, msg) => console.log(`[${phase}] ${msg}`) }); </script>
3
Low-Level Decrypt
Use MeloloDecrypt.decrypt() for manual control. Pass the encrypted CDN URL and hex key, get back a playable Blob.
// 1. Get episode data + key const ep = await fetch('/api/melolo/episode?id=...&ep=1').then(r => r.json()); const quality = ep.qualityList.find(q => q.label === '720p'); const keyData = await fetch('/api/melolo/key?vid=' + quality.kid).then(r => r.json()); // 2. Decrypt — returns a Blob (video/mp4) const blob = await MeloloDecrypt.decrypt(quality.url, keyData.key, (phase, msg) => { console.log(`[${phase}] ${msg}`); // Phases: fetch → decrypt → neutralize → done }); // 3. Play const video = document.getElementById('player'); video.src = URL.createObjectURL(blob); video.play();

Streaming overlap: melolo-decrypt.js starts decrypting samples as soon as their bytes arrive — while the rest of the file is still downloading. This reduces total time by up to 40% compared to download-then-decrypt.

Authentication

All Melolo endpoints require the X-API-Key header.

Rate Limits

PlanRequests / min
Free10
Monthly5,000
LifetimeUnlimited

Example Request

curl -H "X-API-Key: YOUR_KEY" \
{{BASE}}/api/melolo/trending

Supported Languages

Loading...
Endpoints
GET /api/melolo/languages API Key
Returns list of supported languages with codes and names.
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/languages"
GET /api/melolo/trending API Key
Returns trending dramas from Melolo. Alias for foryou — both use the same content feed.
ParameterTypeDescription
langoptionalstringLanguage code (default: id)
pageoptionalintegerPage number (default: 1)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/trending?lang=id"
GET /api/melolo/foryou?page={page} API Key
Returns paginated drama catalog from Melolo. Each page returns 20 items. Same feed as trending and latest.
ParameterTypeDescription
langoptionalstringLanguage code (default: id)
pageoptionalintegerPage number (default: 1)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/foryou?page=1&lang=id"
GET /api/melolo/search?query={keyword}&page={page}&limit={limit} API Key
Search for dramas within Melolo. Supports pagination with page and limit params.
ParameterTypeDescription
queryrequiredstringSearch keyword
pageoptionalintegerPage number (default: 1)
limitoptionalintegerResults per page, max 50 (default: 30)
langoptionalstringLanguage code (default: id)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/search?query=cinta&page=1&limit=30&lang=id"
GET /api/melolo/detail?id={bookId} API Key
Get detailed information about a specific Melolo drama.
ParameterTypeDescription
idrequiredstringBook ID from search or trending results
langoptionalstringLanguage code (default: id)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/detail?id=7430026544543482113&lang=id"
GET /api/melolo/allepisode?id={bookId} API Key
Returns all episodes for a Melolo drama with metadata. For playable video URLs, use the episode endpoint which returns hlsUrl (direct playable MP4).
ParameterTypeDescription
idrequiredstringBook ID
langoptionalstringLanguage code (default: id)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/allepisode?id=7430026544543482113&lang=id"
GET /api/melolo/episode?id={bookId}&ep={number} API Key
Returns full episode data including multi-quality video URLs and a ready-to-play hlsUrl.

Key fields: hlsUrl (direct playable MP4, server-side decrypt), qualityList with per-quality hlsUrl, contentKey (for advanced clients doing their own decrypt).
ParameterTypeDescription
idrequiredstringBook ID
eprequiredintegerEpisode number (1-based)
langoptionalstringLanguage code (default: id)
qoptionalstringQuality label (e.g. 720p)
Example
curl -H "X-API-Key: YOUR_KEY" "{{BASE}}/api/melolo/episode?id=7430026544543482113&ep=1&lang=id"
GET /api/melolo/hls?id={bookId}&ep={number} API Key
Direct playable video. Server fetches the encrypted video from CDN, decrypts it (CENC AES-128-CTR), and streams the clean MP4 to you. Zero client-side DRM — just play this URL like any normal video.

Tip: Use the hlsUrl from the /episode response. Requires API key (either X-API-Key header or api_key query parameter).
ParameterTypeDescription
idrequiredstringBook ID
eprequiredintegerEpisode number (1-based)
langoptionalstringLanguage code (default: id)
qoptionalstringQuality label (e.g. 720p)
api_keyoptionalstringAPI Key (alternative to X-API-Key header, useful for direct video links)
Example (returns MP4 video)
curl -H "X-API-Key: YOUR_KEY" -o video.mp4 "{{BASE}}/api/melolo/hls?id=7430026544543482113&ep=1&lang=id" # Or use api_key query param: curl -o video.mp4 "{{BASE}}/api/melolo/hls?id=7430026544543482113&ep=1&lang=id&api_key=YOUR_KEY"
GET /api/melolo/player?id={bookId}&ep={number} Special
Serves an HTML page that performs client-side CENC-AES-CTR decryption using SubtleCrypto. The browser fetches the encrypted MP4 directly from TikTok CDN, decrypts it in-memory, creates a Blob URL, and plays it — zero bandwidth on our server.
ParameterTypeDescription
idrequiredstringBook ID
eprequiredintegerEpisode number (1-based)
langoptionalstringLanguage code (default: id)
qoptionalstringQuality label (e.g. 720p)
Example (open in browser)
{{BASE}}/api/melolo/player?id=7430026544543482113&ep=1&lang=id
GET /api/melolo/decrypt-info?id={bookId}&ep={number} Special
Returns DRM decryption info (AES key, IV) for a specific Melolo episode. Used by external players or proxy services for CENC-AES-CTR decryption.
ParameterTypeDescription
idrequiredstringBook ID
eprequiredintegerEpisode number (1-based)
langoptionalstringLanguage code (default: id)
qoptionalstringQuality label (e.g. 720p)
Example
curl "{{BASE}}/api/melolo/decrypt-info?id=7430026544543482113&ep=1&lang=id"
DRM Endpoints
GET /api/melolo/key?vid={videoID_or_kid} Public
Returns the AES-128 content key (hex) for a given video ID or Key ID (KID). Used by client-side decrypt players to obtain the decryption key.
ParameterTypeDescription
vidrequiredstringVideo ID or KID from episode qualityList
Example
curl "{{BASE}}/api/melolo/key?vid=v02004g10000cpk..." # Response: # {"key": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"}
POST /api/melolo/license?kid={hex} Public
W3C Clear Key license server. Responds to browser EME (Encrypted Media Extensions) license requests with a JSON Web Key Set (JWKS). Used for native browser DRM playback without custom decrypt code.
ParameterTypeDescription
kidoptionalstringKey ID (hex). Can also be sent in request body as {"kids":["base64url_kid"]}
Example
# Query param method: curl "{{BASE}}/api/melolo/license?kid=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" # EME request body method: curl -X POST -H "Content-Type: application/json" \ -d '{"kids":["obLD1OX2p7jJ0OH...=="]}' \ "{{BASE}}/api/melolo/license" # Response (JWKS format): # {"keys":[{"kty":"oct","kid":"...","k":"..."}],"type":"temporary"}
GET /api/melolo/drm-stream/{videoID} Public
Server-side decrypt stream by video ID. Fetches the encrypted CENC MP4 from TikTok CDN, decrypts it with the stored content key, and streams the clean MP4 with range support. The videoID must have been previously registered via an /episode call.
ParameterTypeDescription
videoIDrequiredpathVideo ID from episode qualityList (path segment, not query param)
Example
# First call /episode to register keys, then: curl -o video.mp4 "{{BASE}}/api/melolo/drm-stream/v02004g10000cpk..." # Supports range requests for seeking: curl -H "Range: bytes=0-1048575" "{{BASE}}/api/melolo/drm-stream/v02004g10000cpk..."
GET /api/melolo/drm-raw/{videoID} Special
Proxies the raw encrypted CENC MP4 from TikTok CDN without decrypting. Useful for EME Clear Key playback or when you want to handle decryption yourself. Pair with /api/melolo/license for browser-native DRM playback.
ParameterTypeDescription
videoIDrequiredpathVideo ID (must be registered via /episode call first)
Example
# Download raw encrypted CENC MP4: curl -o encrypted.mp4 "{{BASE}}/api/melolo/drm-raw/v02004g10000cpk..."
GET /api/melolo/drm-test/{bookID}?ep={number} Special
Service Worker-based DRM player page. Uses a progressive streaming decrypt approach — video starts playing in ~2 seconds while the rest of the file is still downloading and decrypting. Zero server bandwidth (browser fetches directly from TikTok CDN).

Features: episode selector, quality picker, auto-next episode, resolution + duration display.
ParameterTypeDescription
bookIDrequiredpathBook ID (path segment)
epoptionalintegerEpisode number (default: 1)
Example (open in browser)
{{BASE}}/api/melolo/drm-test/7430026544543482113?ep=1
GET /melolo-sw.js Public
Service Worker JavaScript file for progressive streaming decrypt. Must be registered at root path (/melolo-sw.js) so its scope covers /sw-play requests. The SW intercepts /sw-play?url=CDN&key=HEX fetches, downloads encrypted MP4, parses moov early, then streams decrypted bytes progressively.
Registration
// Register in your page: const reg = await navigator.serviceWorker.register('/melolo-sw.js'); // Then set video source: video.src = '/sw-play?url=' + encodeURIComponent(cdnURL) + '&key=' + keyHex;
GET /melolo-decrypt.js Public
Client-side CENC AES-128-CTR decryption library. Streaming overlap decrypt (decrypts while downloading), pre-allocated buffers, parallel sample processing. Exposes MeloloDecrypt.decrypt() and MeloloDecrypt.play() methods. See the JavaScript SDK section above for usage.
Include
<script src="{{BASE}}/melolo-decrypt.js"></script>
DRM Architecture

Encryption: Melolo uses CENC AES-128-CTR (Common Encryption with AES-128 in Counter mode). Each video is an ISO BMFF (MP4) container with encrypted mdat samples. The content key is derived from ByteDance's spade_a blob via a proprietary key derivation function.

Key Storage: Content keys are automatically derived and stored when you call the /episode endpoint. Keys are indexed by both videoID and KID (from the MP4's tenc box). The keystore persists to keys.json on disk.

Decryption Flow (CENC sample-based):

  1. Parse ISO BMFF structure to find moovtrakstbl
  2. Extract per-sample IVs from senc box (8-byte initialization vectors)
  3. Build sample offset table from stsz + stsc + stco
  4. Decrypt each sample: AES-CTR(key, counter=IV||0x00000000, sample_data)
  5. Neutralize DRM markers: encvhvc1, sinf/senc/tencfree

CDN: Encrypted videos are hosted on TikTok's CDN (v3-default.ixigua.com, v26-default.ixigua.com, etc.). Client-side decrypt methods fetch directly from CDN, using zero server bandwidth.

Melolo — Api-Dracin Multi-Source Drama Streaming API