sdk

package
v1.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: AGPL-3.0 Imports: 0 Imported by: 0

README

OpenDeezer SDK

The OpenDeezer SDK is a public Go library that lets third-party developers build on the OpenDeezer engine: the Deezer API client, track decode/decrypt and streaming, LAN device discovery (OpenDeezer Connect), and the remote control API.

go get github.com/Cycl0o0/OpenDeezer

Import paths:

Package Purpose
github.com/Cycl0o0/OpenDeezer/sdk/deezer Deezer API client + decode
github.com/Cycl0o0/OpenDeezer/sdk/connect OpenDeezer Connect (LAN discovery + remote)
github.com/Cycl0o0/OpenDeezer/sdk/control Control server + client (HTTP/JSON API)
github.com/Cycl0o0/OpenDeezer/sdk/player In-process audio playback (cgo)

Go docs: https://pkg.go.dev/github.com/Cycl0o0/OpenDeezer/sdk

Control works both ways (in + out)

Everything that controls a client is available in both directions — you can drive another device (out) and be driven by one (in):

Capability Out (control another) In (be controlled)
Remote control API control.Client control.Server
OpenDeezer Connect connect.Discover + connect.RemoteClient connect.Host (+ connect.Advertise)

Both sides cover the same transport command set: play/pause, next, prev, stop, restart, seek, volume, repeat, shuffle, play-track, play-playlist.


Authentication (ARL)

Deezer uses a long-lived cookie called the ARL (Audio Reference Link) for authentication. Get yours from a browser session: open deezer.com, press F12, go to Application → Cookies → arl.

The ARL never leaves your machine beyond the HTTPS requests made to deezer.com and media.deezer.com.

import dz "github.com/Cycl0o0/OpenDeezer/sdk/deezer"

client := dz.New(os.Getenv("DEEZER_ARL"))
if err := client.Login(); err != nil {
    // errors.Is(err, dz.ErrARLExpired) → ARL needs refreshing
    log.Fatal(err)
}
acc := client.Account()
fmt.Printf("Hello %s (%s)\n", acc.Name, acc.Offer)

Browse

// Search
results, _ := client.Search("Radiohead")
for _, t := range results.Tracks {
    fmt.Println(t.Name, "—", t.ArtistLine())
}

// Charts (global top 50)
charts, _ := client.Charts("0")

// Favorites / playlists (requires login)
tracks, _ := client.Favorites()
playlists, _ := client.Playlists()

// Artist profile
page, _ := client.ArtistProfile("27")   // Radiohead
fmt.Println(page.Artist.Name, page.Artist.NbFans, "fans")

// Lyrics
lyr, _ := client.Lyrics(trackID)
if lyr.IsSynced() {
    for _, line := range lyr.Synced {
        fmt.Printf("%d ms  %s\n", line.TimeMS, line.Text)
    }
}

Download and decrypt a track

PrepareStream resolves the CDN URL and decryption key. DownloadTrack then fetches, decrypts (BF_CBC_STRIPE), and writes the audio bytes to any io.Writer:

import (
    "os"
    dz "github.com/Cycl0o0/OpenDeezer/sdk/deezer"
)

client.SetQuality(dz.QualityHigh) // prefer MP3 320; falls back if not entitled

plan, err := client.PrepareStream(trackID)
if err != nil {
    log.Fatal(err)
}
fmt.Println("Format:", dz.FormatLabel(plan.Format)) // "MP3 · 320 kbps"

f, _ := os.Create("track.mp3")
defer f.Close()
if err := dz.DownloadTrack(plan, f); err != nil {
    log.Fatal(err)
}

Quality levels:

Constant Format Requires
dz.QualityNormal MP3 128 kbps Any account
dz.QualityHigh MP3 320 kbps Premium
dz.QualityLossless FLAC HiFi

Deezer falls back to the highest quality the account is entitled to automatically.

Decrypt an in-memory buffer
plain, err := dz.DecryptBytes(trackID, encryptedBytes)

OpenDeezer Connect (LAN discovery + remote)

OpenDeezer Connect is symmetric — the SDK exposes both directions:

Direction What API
out discover + control other devices connect.Discover, connect.RemoteClient
in be discoverable + controllable connect.Host (or connect.Advertise for the discovery half alone)
Out — discover and drive a device
import "github.com/Cycl0o0/OpenDeezer/sdk/connect"

// Find devices (2-second probe window).
devices, _ := connect.Discover(2*time.Second, 0)
for _, d := range devices {
    fmt.Printf("%s at %s\n", d.Name, d.Addr)
}

// Drive the first device (same-account auth — no token needed).
rc := connect.NewRemoteClient(devices[0].Addr, "", myUserID)
st, _ := rc.PlayPause()
fmt.Println("state:", st.State)
In — be a controllable device

connect.Host ties a control endpoint together with LAN advertising. The device accepts the exact command set a RemoteClient sends:

host := connect.NewHost(
    connect.HostConfig{
        Control: connect.Config{Addr: ":7654", SameAccountOnly: true},
        Name:    "My Player", Client: "myapp", Version: "1.0",
    },
    func() connect.State { return currentState() },
    func() connect.Account {
        a := client.Account()
        return connect.Account{UserID: a.UserID, Name: a.Name, Offer: a.Offer}
    },
    connect.Commands{
        PlayPause: player.TogglePause,
        Stop:      player.Stop,
        SetVolume: player.SetVolume,
        PlayTrack: playByID,
    },
    client, // browse routes; nil to disable
)
host.Start()
defer host.Close()
// host.Server().EnablePairing() to also accept the phone web remote.

If you already run your own control server, advertise the discovery half alone:

resp, _ := connect.Advertise(func() connect.AdvertiseInfo {
    return connect.AdvertiseInfo{Name: "My Player", Client: "myapp", Version: "1.0"}
}, controlPort)
defer resp.Close()
Auth modes for RemoteClient

Check Whoami.Auth on the target device to know which credential to supply:

Auth What to pass
"token" token="<bearer-token>"
"account" accountID="<your Deezer user id>"
"session" Not controllable from RemoteClient/control.Client; driveable only from the device's embedded browser remote, which sends a paired session token in the X-OpenDeezer-Session header (stored in localStorage, not a cookie)
"none" Empty strings

Remote control (server = in, client = out)

The control API is also symmetric: control.Server hosts a controllable endpoint (in), control.Client drives one (out).

Control server (in)

Host a controllable endpoint that phones, AI agents, or other OpenDeezer clients can drive.

import "github.com/Cycl0o0/OpenDeezer/sdk/control"

srv := control.NewServer(
    control.Config{
        Addr:  ":7654",
        Token: "my-secret-token",
    },
    func() control.State { return currentState() },
    func() control.Account {
        a := client.Account()
        return control.Account{UserID: a.UserID, Name: a.Name, Offer: a.Offer}
    },
    control.Commands{
        PlayPause: player.TogglePause,
        Next:      queue.Next,
        Stop:      player.Stop,
        Seek:      player.SeekMS,
        SetVolume: player.SetVolume,
    },
    client, // for GET /search and GET /playlists; nil to disable
)
srv.SetVersion("1.0")
srv.Start()
defer srv.Close()
Phone web remote

Enable pairing to let a phone control playback via a browser:

srv := control.NewServer(
    control.Config{Addr: ":7654", WebRemote: true},
    ...
)
srv.Start()
code := srv.EnablePairing() // display this 6-digit code to the user
fmt.Printf("Open http://192.168.1.X:7654/remote — code: %s\n", code)
Control client (out)
c := control.NewClient("http://192.168.1.5:7654", "my-secret-token", "")
st, _ := c.Status()
fmt.Println(st.State, st.Track.Title)
c.SetVolume(0.8)
c.SeekMS(30000)
c.PlayTrack("3135556")

In-process playback (cgo)

The sdk/player package wraps the audio engine (miniaudio/malgo or oto, selected by build tag). It requires cgo. Omit this import if you only need API access, search, or download/decrypt.

import (
    "github.com/Cycl0o0/OpenDeezer/sdk/player"
    dz "github.com/Cycl0o0/OpenDeezer/sdk/deezer"
)

p, _ := player.NewPlayer()
defer p.Close()

p.SetReplayGain(true)
p.SetVolume(0.9)

// Play a track.
plan, _ := client.PrepareStream(trackID)
p.Play(plan, track.DurationMS)

// Advance queue when track ends.
p.SetOnFinish(func() { /* load next */ })

// Gapless: preload the next track before this one ends.
nextPlan, _ := client.PrepareStream(nextTrackID)
p.Preload(nextPlan, nextTrack.DurationMS)

Examples

Runnable examples are in examples/:

Directory Direction What it shows
examples/search Login + search + print results
examples/download Login → PrepareStream → DownloadTrack → file
examples/connect out Discover LAN devices + send PlayPause
examples/host in Be a discoverable, controllable Connect device
examples/remote-server in Host a control server + poll it via the client

Run any example with:

DEEZER_ARL=<your_arl> go run ./examples/search "Daft Punk"
DEEZER_ARL=<your_arl> go run ./examples/download 3135556
DEEZER_ARL=<your_arl> go run ./examples/connect
DEEZER_ARL=<your_arl> go run ./examples/host
DEEZER_ARL=<your_arl> go run ./examples/remote-server

Documentation

Overview

Package sdk is the OpenDeezer public SDK — a curated Go API for third-party developers who want to build on the OpenDeezer engine without forking the application itself.

Sub-packages

  • sdk/deezer — Deezer API client (login, browse, stream resolution, decrypt)
  • sdk/connect — OpenDeezer Connect (LAN device discovery, remote playback)
  • sdk/control — control server + client (HTTP/JSON remote-control API)
  • sdk/player — in-process audio playback (cgo required: miniaudio or oto)

Install

go get github.com/Cycl0o0/OpenDeezer

Quick start

import (
    dz "github.com/Cycl0o0/OpenDeezer/sdk/deezer"
)

client := dz.New(os.Getenv("DEEZER_ARL"))
if err := client.Login(); err != nil {
    log.Fatal(err)
}
results, _ := client.Search("Daft Punk")
for _, t := range results.Tracks {
    fmt.Println(t.Name, "-", t.ArtistLine())
}

ARL authentication

Deezer uses a long-lived cookie called the ARL (Audio Reference Link) for authentication. Obtain yours from a browser session (Application > Cookies > arl on deezer.com) and pass it to sdk/deezer.New. The ARL never leaves your machine beyond the HTTPS requests made to Deezer.

Directories

Path Synopsis
Package connect implements OpenDeezer Connect: LAN discovery and remote control of OpenDeezer devices, in both directions.
Package connect implements OpenDeezer Connect: LAN discovery and remote control of OpenDeezer devices, in both directions.
Package control exposes the OpenDeezer remote-control API: a small HTTP/JSON server that a controller (another OpenDeezer client, an MCP agent, a phone web remote) can drive, and a matching client that talks to one.
Package control exposes the OpenDeezer remote-control API: a small HTTP/JSON server that a controller (another OpenDeezer client, an MCP agent, a phone web remote) can drive, and a matching client that talks to one.
Package deezer is the OpenDeezer SDK's Deezer API layer: account login via ARL, browse (favorites, playlists, albums, search, charts, Flow, artists, lyrics, podcasts), library write operations (like/unlike, playlist CRUD), stream resolution, and Blowfish BF_CBC_STRIPE decryption.
Package deezer is the OpenDeezer SDK's Deezer API layer: account login via ARL, browse (favorites, playlists, albums, search, charts, Flow, artists, lyrics, podcasts), library write operations (like/unlike, playlist CRUD), stream resolution, and Blowfish BF_CBC_STRIPE decryption.
Package player provides in-process Deezer audio playback via Player.
Package player provides in-process Deezer audio playback via Player.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL