184 lines
8.3 KiB
Markdown
Executable File
184 lines
8.3 KiB
Markdown
Executable File
---
|
||
title: Yandex Music API — выгрузка библиотеки
|
||
updated: '2026-09-26'
|
||
type: tech
|
||
tags:
|
||
- music
|
||
- yandex
|
||
- api
|
||
- personal
|
||
related: personal/spotify-library
|
||
---
|
||
|
||
# Yandex Music API — выгрузка библиотеки
|
||
|
||
> Рабочий метод выгрузки лайков, плейлистов и альбомов из Яндекс Музыки
|
||
> **БЕЗ OAuth-флоу** — токен лежит в Local Storage desktop-приложения.
|
||
> Проверено живыми запросами: 2026-09-26.
|
||
> Skill: `yandex-music-library-export` (`~/.hermes/hermes-whale/skills/media/`)
|
||
|
||
---
|
||
|
||
## 1. Извлечение токена (главное)
|
||
|
||
Desktop-приложение Яндекс Музыки хранит OAuth-токен в **Local Storage LevelDB** в открытом виде (без шифрования, не в Keychain).
|
||
|
||
**Путь:**
|
||
```
|
||
~/Library/Application Support/YandexMusic/Local Storage/leveldb/
|
||
```
|
||
Файлы: `000394.log`, `000396.ldb` — **номер файла меняется**, искать по маске `*.ldb` / `*.log`.
|
||
|
||
**Формат токена:** `y0_` + ~56 символов base64url (итого ~59-60 символов).
|
||
|
||
```bash
|
||
LS="$HOME/Library/Application Support/YandexMusic/Local Storage/leveldb"
|
||
find "$LS" -type f \( -name "*.ldb" -o -name "*.log" \) \
|
||
| while read f; do strings "$f" | grep -oE "y0_[A-Za-z0-9_.-]{20,}"; done \
|
||
| head -1 > /tmp/ym_token
|
||
chmod 600 /tmp/ym_token
|
||
```
|
||
|
||
### Что НЕ работает — не тратить время
|
||
|
||
| Источник | Результат |
|
||
|---|---|
|
||
| `YandexMusic/Cookies` (Session_id, sessionid2) | ❌ HTTP 401 |
|
||
| Keychain (`security find-generic-password -s "Yandex Music Safe Storage"`) | ❌ Записи не существует |
|
||
| `IndexedDB/*.leveldb/*.log` | ❌ Токена нет, там кэш |
|
||
| `Preferences`, `.updaterId` | ❌ Только UUID и настройки |
|
||
|
||
**Важно:** `sessionid2` содержит суффикс `fakesign000...` — это заглушка, реальная авторизация идёт через OAuth-токен.
|
||
|
||
---
|
||
|
||
## 2. uid пользователя
|
||
|
||
```bash
|
||
H="Authorization: OAuth $(cat /tmp/ym_token)"
|
||
curl -s -H "$H" "https://api.music.yandex.net/account/status" | jq -r '.result.account.uid'
|
||
# → 16635693
|
||
```
|
||
|
||
Заголовок — именно **`OAuth`**, не `Bearer`.
|
||
|
||
---
|
||
|
||
## 3. Проверенные эндпоинты
|
||
|
||
База: `https://api.music.yandex.net`
|
||
|
||
| Что | Endpoint | Проверено |
|
||
|---|---|---|
|
||
| Статус аккаунта + uid | `GET /account/status` | ✅ |
|
||
| Настройки | `GET /account/settings` | ✅ |
|
||
| **Лайкнутые треки** | `GET /users/{uid}/likes/tracks` | ✅ 956 треков |
|
||
| **Плейлисты** | `GET /users/{uid}/playlists/list` | ✅ 8 штук |
|
||
| Лайкнутые альбомы | `GET /users/{uid}/likes/albums` | ✅ 100 |
|
||
| Метаданные треков | `GET /tracks?track-ids=ID1,ID2,...` | ✅ title/artists/albums |
|
||
|
||
### Ответ `likes/tracks` — только id и timestamp!
|
||
|
||
```json
|
||
{
|
||
"result": {
|
||
"library": {
|
||
"tracks": [
|
||
{"id": "149422838", "albumId": "41220806", "timestamp": "2026-08-27T02:05:47+00:00"}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
`timestamp` — дата лайка. Названий и артистов НЕТ — нужен второй запрос на `/tracks` батчами по ~100 id.
|
||
|
||
### Ответ `playlists/list`
|
||
|
||
```json
|
||
[{"kind": 1009, "title": "Классика", "trackCount": 3}]
|
||
```
|
||
Параметр `?with-tracks=true` добавляет треки в тот же ответ.
|
||
|
||
---
|
||
|
||
## 4. Прослушанное (история) — НЕ ДОСТУПНО ⛔
|
||
|
||
Ни один из вариантов не существует в публичном API:
|
||
|
||
| Endpoint | Ответ |
|
||
|---|---|
|
||
| `/users/{uid}/history` | `not-found` |
|
||
| `/users/{uid}/music-history` | `not-found` |
|
||
| `/users/{uid}/recent-tracks` | `not-found` |
|
||
| `/users/{uid}/play-history` | `not-found` |
|
||
| `/users/{uid}/plays` | `not-found` |
|
||
| `/users/{uid}/listening` | `not-found` |
|
||
|
||
`GET /landing3?blocks=personal-playlists` возвращает блоки, но `data.title: null` — контент скрыт за авторизацией веб-клиента.
|
||
|
||
**Вывод:** историю прослушивания Яндекс через этот API не отдаёт.
|
||
|
||
---
|
||
|
||
## 5. Spotify — токен НЕ найден ⛔
|
||
|
||
Проверено (2026-09-26), ни одного `sp_dc` / `sp_t` / `access_token`:
|
||
|
||
| Место | Результат |
|
||
|---|---|
|
||
| Desktop app `PersistentCache/public.ldb/*.log` | ❌ Только телеметрия |
|
||
| `Users/<id>-user/prefs` | ❌ Только настройки UI и DIAL-устройства |
|
||
| Keychain `Spotify Safe Storage` | ❌ Записи не существует |
|
||
| Chrome (Default, Profile 4, Guest) | ❌ 0 spotify-cookies |
|
||
| Firefox (3 профиля) | ❌ 0 |
|
||
| Safari (`Cookies.binarycookies`) | ❌ 0 |
|
||
| Arc / Brave | ❌ Профилей нет |
|
||
|
||
**Приложение Spotify на Mac не пишет cookies на диск.** Токен либо в памяти, либо в Keychain под другим именем.
|
||
|
||
**Рабочие варианты (не проверялись):**
|
||
1. `spotify.com/account/privacy` → **Request data** (Extended streaming history) — ZIP на email
|
||
2. Official Web API `GET /v1/me/tracks` — требует OAuth-приложения в Developer Dashboard
|
||
3. `sp_dc` из залогиненной веб-сессии `open.spotify.com`
|
||
|
||
---
|
||
|
||
## 6. Итоговое состояние (2026-09-26)
|
||
|
||
| | Яндекс Музыка | Spotify |
|
||
|---|---|---|
|
||
| Токен | ✅ `y0_...` в `/tmp/ym_token` | ❌ нет |
|
||
| uid | `16635693` (login mAlleXXX) | `mixsxmcds20znczu4na52ghox` |
|
||
| Лайки | ✅ 956 треков | ⚠️ 162 (данные в [[personal/spotify-library]] от 2026-05-12) |
|
||
| Плейлисты | ✅ 8 штук | ⚠️ 6 (2026-05-12) |
|
||
| Альбомы | ✅ 100 | ⚠️ 40 (2026-05-12) |
|
||
| История | ❌ API не отдаёт | ❌ токена нет |
|
||
|
||
**8 плейлистов Яндекс:** Классика (3), ДР (3), ok (4), олдскуд (3), Слушать позже (34), Best (1), Мои аудиозаписи ВКонтакте (237), Мегаpolice - АК-47 (20)
|
||
|
||
### Статус (2026-09-26)
|
||
- **Яндекс — ГОТОВО:** `personal/yandex-music-library.md` — 956 лайков (с датами), 8 плейлистов (321 трек), 100 альбомов. 1456 строк, 117 KB. Добавлено в `personal/index.md`.
|
||
- **Spotify — блокер:** `~/.hermes/auth.json` → `.providers.spotify` содержит client_id + refresh_token, но токен **отозван** (`invalid_grant: Refresh token revoked`) → `SpotifyAuthRequiredError`. Нужен `hermes auth spotify` (интерактивно, браузер).
|
||
|
||
---
|
||
|
||
## 7. Подводные камни
|
||
|
||
- **`$(...)` внутри write_file может быть вырезан** санитайзером → `syntax error near unexpected token )`. Решение: писать скрипт без inline-подстановок, читать токен из файла; либо `source /dev/stdin <<'EOF'`.
|
||
- **Не эхоить токен в stdout** — попадает в лог сессии. Писать в `/tmp/ym_token` с `chmod 600`.
|
||
- **Токен привязан к устройству и обновляется** — при 401 перечитать из LevelDB (приложение должно быть запущено и залогинено).
|
||
- **Токен в `/tmp` сбрасывается при перезагрузке** — извлекать заново.
|
||
- **Не пихать 956 id в один URL** `/tracks?track-ids=` — бить на батчи по ~100.
|
||
- **uid `0` не работает**: `/users/0/likes/tracks` → `invalid uid: 0`. Только реальный uid.
|
||
|
||
---
|
||
|
||
## 8. Связанные документы
|
||
|
||
- [[personal/spotify-library]] — выгрузка Spotify (2026-05-12)
|
||
- [[personal/music-download-practices]] — источники mp3, загрузка на TrueNAS
|
||
- [[personal/documents/music-recommendations]] — музыкальные рекомендации
|
||
|
||
---
|
||
*Создано: 2026-09-26 | Сессия: разведка способов выгрузки Яндекс Музыки и Spotify*
|