Skip to content

Instantly share code, notes, and snippets.

@in4in-dev
Last active August 20, 2026 05:12
Show Gist options
  • Select an option

  • Save in4in-dev/09f32f313f11b2c10778d9e2ffe7e60e to your computer and use it in GitHub Desktop.

Select an option

Save in4in-dev/09f32f313f11b2c10778d9e2ffe7e60e to your computer and use it in GitHub Desktop.
PHP VK audio unmask (decode extras)
<?php
//(js -> php) code. letter by letter
global $n, $i, $id;
$n = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=";
$id = 12345; //YOUR USER ID
$i = [
'v' => function($e) {
return strrev($e);
},
'r' => function($e, $t){
global $n;
$e = str_split($e);
for ($o = $n . $n, $s = count($e); $s--;){
$i = stripos($o, $e[$s]);
if(~$i){
$e[$s] = substr($o, $i - $t, 1);
}
}
return implode("", $e);
},
's' => function($e, $t) {
$n = strlen($e);
if ($n) {
$i = r($e, $t);
$o = 0;
$e = str_split($e);
for (; ++$o < $n;){
$p = array_splice($e, $i[$n - 1 - $o], 1, $e[$o]);
$e[$o] = $p[0];
}
$e = implode("", $e);
}
return $e;
},
'i' => function($e, $t){
global $i, $id;
$k = $i['s'];
return $k($e, $t ^ $id);
},
];
function o() {
return false;
}
function a($e){
global $n;
if (!$e || strlen($e) % 4 == 1) {
return !1;
}
$s = 0;
for ($o = 0, $a = "";$s < strlen($e);) {
$i = $e[$s++];
$i = strpos($n, $i);
if ($i !== false) {
$t = ($o % 4) ? 64 * $t + $i : $i;
if ($o++ % 4) {
$a .= chr(255 & $t >> (-2 * $o & 6));
}
}
}
return $a;
}
function r($e, $t) {
$n = strlen($e);
$i = [];
if ($n) {
$o = $n;
$t = abs($t);
for (; $o--;){
$t = ($n * ($o + 1) ^ $t + $o) % $n;
$i[$o] = $t;
}
}
return $i;
}
function s($e){
global $i;
if (!o() && strpos($e, "audio_api_unavailable") !== false) {
$t = explode("?extra=", $e);
$t = $t[1];
$t = explode("#", $t);
$n = ("" === $t[1]) ? "" : a($t[1]);
$t = a($t[0]);
if (!is_string($n) || !$t){ return $e;}
$n = $n ? explode(chr(9), $n) : [];
for ($l = count($n); $l--;) {
$r = explode(chr(11), $n[$l]);
$s = array_splice($r, 0, 1, $t);
$s = $s[0];
if (!$i[$s]){ return $e; }
$t = $i[$s](...$r);
}
if ($t && "http" === substr($t, 0, 4)){ return $t;}
}
return $e;
}
//For example
//EASY <><<><><>
//$extra = s("https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=encodevaluefromvk"); //Encode extra url -> Good extra url
//Or see -> test.php
<?php
include_once(__DIR__ . "/perfect.php");
$email = ""; //Login
$pass = ""; //Pass
$auth_url = "https://m.vk.com";
if(array_key_exists("extra", $_GET)){
header("Content-type: audio/mpeg");
echo file_get_contents(urldecode($_GET['extra']));
}else {
/* Auth .. Copied from stackoverflow */
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$login_page = curl_exec($ch);
curl_close($ch);
preg_match("/<form method=\"post\" action=\"([^\"]+)/", $login_page, $login_url);
$login_url = $login_url[1];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, ["email" => $email, "pass" => $pass]);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_exec($ch);
curl_close($ch);
/* Get music */
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://m.vk.com/audio");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Requested-With: XMLHttpRequest']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, ["_ajax" => 1, 'q' => $_GET['search']]);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$page = curl_exec($ch);
curl_close($ch);
$html = json_decode($page, true);
$html = $html[3][0];
$html = mb_convert_encoding($html, "UTF-8", "windows-1251");
preg_match_all('/<span class="ai_title">(.+?)<\/span>/', $html, $titles);
$titles = $titles[1];
preg_match_all('/<span class="ai_artist">(.+?)<\/span>/', $html, $artists);
$artists = $artists[1];
//Get extras
preg_match_all('/"https:\/\/m\.vk\.com\/mp3\/audio_api_unavailable\.mp3\?extra=([^"]+)/', $html, $extras);
$extras = $extras[1];
$result = array();
foreach ($titles as $k => $title) {
$result[] = array(
"title" => strip_tags($title),
"artist" => strip_tags($artists[$k]),
"extra" => s("https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=" . $extras[$k]) //Decooooooode
);
}
/* Html */
?>
<!doctype html>
<html lang="ru">
<head>
<meta charset="windows-1251">
<title>Document</title>
</head>
<body>
<?php
echo "<table>";
foreach ($result as $val) {
echo "<tr>";
echo("<td>" . mb_convert_encoding($val['title'], "CP1251", "UTF8") . "</td><td>" . mb_convert_encoding($val['artist'], "CP1251", "UTF8") . "</td><td><a href='" . ("?extra=" . $val['extra']) . "'>Получить</a></td>");
echo "</tr>";
}
echo "</table>";
?>
</body>
</html>
<?php
}
@Va1b0rt

Va1b0rt commented Jan 16, 2021

Copy link
Copy Markdown

@Va1b0rt

Va1b0rt commented Jan 16, 2021

Copy link
Copy Markdown

Ничего в вашем php не понимаю..... Беда

@in4in-dev

Copy link
Copy Markdown
Author

А вот от чего моя ссылка, например, https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=AhfTzgqToguXlNv6rgj3AtfLDgnXqMiOAOLRDM0ZDZvdtgq3m3jRDdbLrY8YzejdAwrHtM1Nwgvttg5vr2GUrhm4zc9UqZO5qxvNl3jOzefMA1vPmgfHAwrHDfiXqZbiD1DJqMKXDI5oDdnTv1bpCI94zdnMCdfZBJz4mvH1zxGVmhn2mgH2Awy1B3n1rhDcu1rOtcOWsJqYn1D1CMKWmgHhte9qAdvKswHWu3yZuJzznxn2rdfevMvZv2fotNaOBM43pZfLmfHNsNruCdbkC1mOmO9tsw9VlMzLlZuWtOvtoG#AqSOnda
дешифруется как линк на скачивание файла .m3u8
https://sgi1.is74.vkuseraudio.net/p1/608ef5dc1/dd035ba00900dd/index.m3u8?extra=vB5p14PvSvNoXS-gIjIi4ED6tr-hhTec1uTLtC2nkgDWSwJasODCG3CnebhqUOnkN0WdBIS0SJWO4pmXtX2P7SAw0Wd03Buf1Dh0okBDsGHLvGNa1m51ifwxf3dURhLe7qJiszL5AORvrNCwV3Y
Я что-то не то подсунул?

Это значит, что ответом вам является m3u8 - плейлист его распарсить нужно.

В общем-то на момент января 2021 там теперь отдается .m3u8 файл, это список со ссылками на потоковые (.ts) файлы. Придется скачать файл m3u8, проставить ссылкам домен (они изначально относительные) и использовать что-то типа ffmpeg (натравите его на m3u8 и будет красота) для конвертации в mp3.

Я недавно на заказ опять писал решение)) они каждый месяц усложняют))

@in4in-dev

Copy link
Copy Markdown
Author

Ничего в вашем php не понимаю..... Беда

Там особо нечего понимать))

@whakru

whakru commented Apr 3, 2021

Copy link
Copy Markdown

Не работает(

@QuadVector

Copy link
Copy Markdown

ВК как обычно вставили палку в колеса, нужно обновление(

@TvSpichkin

TvSpichkin commented Jul 31, 2021

Copy link
Copy Markdown

Какой-то геморрой в качестве решения предлагаете. Там делов-то, одну строчку правильно порезать и даже ничего скачивать не нужно...

Вот рабочий пример на 31.07.2021 (извиняюсь, что на js):

var id = 0, // Ваш ID в ВК
ni = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=",
ii = {
    v: function(e) {
        return e.split("").reverse().join("")
    },
    r: function(e, t) {
        var n;
        e = e.split("");
        for (var i = ni + ni, a = e.length; a--;) ~(n = i.indexOf(e[a])) && (e[a] = i.substr(n - t, 1));
        return e.join("")
    },
    s: function(e, t) {
        var n = e.length;
        if (n) {
            var i = function(e, t) {
                    var n = e.length,
                        i = [];
                    if (n) {
                        var a = n;
                        for (t = Math.abs(t); a--;) t = (n * (a + 1) ^ t + a) % n, i[a] = t
                    }
                    return i
                }(e, t),
                a = 0;
            for (e = e.split(""); ++a < n;) e[a] = e.splice(i[n - 1 - a], 1, e[a])[0];
            e = e.join("")
        }
        return e
    },
    i: function(e, t) {
        return ii.s(e, t ^ id)
    },
    x: function(e, t) {
        var n = [];
        return t = t.charCodeAt(0), each(e.split(""), (function(e, i) {
            n.push(String.fromCharCode(i.charCodeAt(0) ^ t))
        })), n.join("")
    }
};

function ai(e) {
    if ((!window.wbopen || !~(window.open + "").indexOf("wbopen")) && ~e.indexOf("audio_api_unavailable")) {
        var t, n, i = e.split("?extra=")[1].split("#"),
            a = "" === i[1] ? "" : oi(i[1]);
        if (i = oi(i[0]), "string" != typeof a || !i) return e;
        for (var o = (a = a ? a.split(String.fromCharCode(9)) : []).length; o--;) {
            if (t = (n = a[o].split(String.fromCharCode(11))).splice(0, 1, i)[0], !ii[t]) return e;
            i = ii[t].apply(null, n)
        }
        if (i && "http" === i.substr(0, 4)) return i
    }
    return e
}

function oi(e) {
    if (!e || e.length % 4 == 1) return !1;
    for (var t, n, i = 0, a = 0, o = ""; n = e.charAt(a++);) ~(n = ni.indexOf(n)) && (t = i % 4 ? 64 * t + n : n, i++ % 4) && (o += String.fromCharCode(255 & t >> (-2 * i & 6)));
    return o
}

function getURL_MP3(str) {
    var arr = ai(str).split("/");
    arr[6] = arr[5] + ".mp3?" + arr[6].split('?')[1];
    arr.splice(4, 2);
    return arr.join("/");
}

@mduplifting

Copy link
Copy Markdown

Всем привет, в начале 22 года не работает
случайно нет рабочего кода у кого нибудь?

@whakru

whakru commented Jan 13, 2022

Copy link
Copy Markdown

Всем привет, в начале 22 года не работает
случайно нет рабочего кода у кого нибудь?

Кури в сторону питона. Там есть рабочие библиотеки по ВК. К сожалению названия не помню.

@Va1b0rt

Va1b0rt commented Jan 13, 2022

Copy link
Copy Markdown

Та есть. Одна единственная. Но рабочая))

@Stmol

Stmol commented Aug 20, 2026

Copy link
Copy Markdown
<?php

declare(strict_types=1);

final class VkExtraDecoder
{
    private const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=';

    private int $userId;

    public function __construct(int $userId = 12345)
    {
        $this->userId = $userId;
    }

    public function decode(string $url): string
    {
        if (!str_contains($url, 'audio_api_unavailable')) {
            return $url;
        }

        $extra = $this->extractExtra($url);
        if ($extra === null) {
            return $url;
        }

        [$encodedPayload, $encodedCommands] = $extra;

        $payload = $this->decodeCustomBase64($encodedPayload);
        $commandsRaw = $encodedCommands !== '' ? $this->decodeCustomBase64($encodedCommands) : '';

        if (!is_string($payload) || $payload === '' || $commandsRaw === null) {
            return $url;
        }

        $commands = $commandsRaw !== '' ? explode("\t", $commandsRaw) : [];

        $current = $payload;
        foreach (array_reverse($commands) as $cmd) {
            $parts = explode("\v", $cmd);
            $op = array_shift($parts);
            $handler = $this->getHandler($op);
            if ($handler === null) {
                return $url;
            }
            $current = $handler($current, ...$parts);
        }

        return str_starts_with($current, 'http') ? $current : $url;
    }

    private function extractExtra(string $url): ?array
    {
        $pos = strpos($url, '?extra=');
        if ($pos === false) return null;

        $extra = substr($url, $pos + 7);
        [$p1, $p2] = explode('#', $extra, 2) + ['', ''];
        return [$p1, $p2];
    }

    private function decodeCustomBase64(string $data): ?string
    {
        if ($data === '' || strlen($data) % 4 === 1) {
            return null;
        }

        $alphabet = self::ALPHABET;
        $out = '';
        $t = 0;
        $o = 0;

        for ($s = 0; $s < strlen($data); $s++) {
            $i = strpos($alphabet, $data[$s]);
            if ($i === false) continue;

            $t = ($o % 4) ? 64 * $t + $i : $i;
            if ($o++ % 4) {
                $out .= chr(255 & $t >> (-2 * $o & 6));
            }
        }

        return $out;
    }

    private function getHandler(string $op): ?callable
    {
        return match ($op) {
            'v' => fn(string $e): string => strrev($e),
            'r' => fn(string $e, int $t): string => $this->shiftAlphabet($e, $t),
            's' => fn(string $e, int $t): string => $this->shuffleString($e, $t),
            'i' => fn(string $e, int $t): string => $this->shuffleString($e, $t ^ $this->userId),
            default => null,
        };
    }

    private function shiftAlphabet(string $e, int $t): string
    {
        $alphabet = self::ALPHABET . self::ALPHABET;
        $chars = str_split($e);
        foreach ($chars as $s => $c) {
            $i = stripos($alphabet, $c);
            if ($i !== false) {
                $chars[$s] = substr($alphabet, $i - $t, 1);
            }
        }
        return implode('', $chars);
    }

    private function shuffleString(string $e, int $t): string
    {
        $n = strlen($e);
        if ($n === 0) return $e;

        $perm = $this->buildPermutation($e, $t);
        $chars = str_split($e);
        for ($o = 1; $o < $n; $o++) {
            $src = $perm[$n - 1 - $o];
            $tmp = $chars[$src];
            $chars[$src] = $chars[$o];
            $chars[$o] = $tmp;
        }
        return implode('', $chars);
    }

    private function buildPermutation(string $e, int $t): array
    {
        $n = strlen($e);
        $perm = [];
        $t = abs($t);
        for ($o = $n - 1; $o >= 0; $o--) {
            $t = ($n * ($o + 1) ^ $t + $o) % $n;
            $perm[$o] = $t;
        }
        return $perm;
    }
}
$decoder = new VkExtraDecoder(12345);
$finalUrl = $decoder->decode('https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=...');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment