Skip to content

Instantly share code, notes, and snippets.

@Ascor8522
Created November 26, 2025 00:00
Show Gist options
  • Select an option

  • Save Ascor8522/14da1671cf8b9b60d426ddbe3b366488 to your computer and use it in GitHub Desktop.

Select an option

Save Ascor8522/14da1671cf8b9b60d426ddbe3b366488 to your computer and use it in GitHub Desktop.
Script to download, patch and install ReVanced APKs
# revanced.ps1
#
# DESCRIPTION:
# ============
# Script to download, patch and install ReVanced APKs.
#
# COPYRIGHT AND LICENSE:
# ======================
# Copyright (c) 2025 Ascor8522
# Licensed under the MIT License
#
# REQUIREMENTS:
# =============
# - PowerShell 7+
# - Out-ConsoleGridView module
# - Java installed and in PATH
# - ADB installed and in PATH
Function New-TemporaryFolder {
$File = New-TemporaryFile
Remove-Item $File -Force
New-Item -Itemtype Directory -Path "$($ENV:Temp)\$($File.Name)"
}
$tmpDir = New-TemporaryFolder
$cliPath = "$tmpDir\revanced-cli.jar"
$patchesPath = "$tmpDir\patches.rvp"
$apps = @(
@{
package = "com.google.android.apps.youtube.music"
revancedPackage = "app.revanced.android.apps.youtube.music"
apkPath = "$tmpDir\YouTubeMusic.apk"
patchedApkPath = "$tmpDir\YouTubeMusic-patched.apk"
apkMirrorDeveloper = "google-inc"
apkMirrorAppName = "youtube-music"
apkMirrorApkName = "youtube-music-VERSION-release"
},
@{
package = "com.google.android.youtube"
revancedPackage = "app.revanced.android.youtube"
apkPath = "$tmpDir\YouTube.apk"
patchedApkPath = "$tmpDir\YouTube-patched.apk"
apkMirrorDeveloper = "google-inc"
apkMirrorAppName = "youtube"
apkMirrorApkName = "youtube-VERSION-release"
}
)
$arch = @("armeabi-v7a", "universal")
$dpi = "nodpi"
Function Download-RevancedCli {
$latestReleaseUrl = "https://api.github.com/repos/ReVanced/revanced-cli/releases/latest"
$jarUrl = Invoke-RestMethod -Uri $latestReleaseUrl
| % { $_.assets }
| Where-Object { $_.name -like "*.jar" }
| Select-Object -ExpandProperty browser_download_url
Invoke-WebRequest -Uri $jarUrl -OutFile $cliPath
Write-Host "Downloaded revanced-cli to $cliPath"
}
Function Download-Patches {
$latestReleaseUrl = "https://api.github.com/repos/ReVanced/revanced-patches/releases/latest"
$rvpUrl = Invoke-RestMethod -Uri $latestReleaseUrl
| % { $_.assets }
| Where-Object { $_.name -like "*.rvp" }
| Select-Object -ExpandProperty browser_download_url
Invoke-WebRequest -Uri $rvpUrl -OutFile $patchesPath
Write-Host "Downloaded revanced-patches to $patchesPath"
}
Function Get-Apk-Versions($app) {
$exp = "(?<version>\d+\.\d+\.\d+) \((?<patches>\d+) patches\)"
$versions = & java -jar $cliPath list-versions -f $app.package $patchesPath
| Out-String
| Select-String $exp -AllMatches
| % { $_.matches }
| % { [PSCustomObject]@{
Version = $_.Groups['version'].Value;
Patches = [int]$_.Groups['patches'].Value;
} }
| Sort-Object -Property Version -Descending
Write-Host "Found $($versions.Count) versions"
return $versions
}
Function Select-Apk-Version($versions, $app) {
$version = $versions
| Out-ConsoleGridView -OutputMode Single -Title "Select version for $($app.package)" -UseNetDriver
| Select-Object -ExpandProperty Version
Write-Host "Selected version $version"
return $version
}
Function Get-Apk-Version-Arch-Dpi-Url($app, $version) {
$versionDashes = $version -replace "\.","-"
$apkName = $app.apkMirrorApkName -replace "VERSION",$versionDashes
$apkPageUrl = "https://www.apkmirror.com/apk/$($app.apkMirrorDeveloper)/$($app.apkMirrorAppName)/$($apkName)/"
$exp = '(?<=<div class="table-cell rowheight addseparator expand pad dowrap">)((?:.|\n)*?)(?=<\/div>)'
$response = Invoke-WebRequest -Uri $apkPageUrl
| % { $_.Content }
| % { $_ -replace '<head>(.|\n)*?</head>', '' }
| % { $_ -replace '<svg(>| )(.|\n)*?</svg>', '' }
| % { $_ -replace '<input(>| )(.|\n)*?>', '' }
| % { $_ -replace '<img(>| )(.|\n)*?>', '' }
| % { $_ -replace '<script(>| )(.|\n)*?</script>', '' }
| % { $_ -replace '<style(>| )(.|\n)*?</style>', '' }
| % { $_ -replace '<br[^>]*/?>', ' ' }
| % { $_ -replace '(?<=>[^<]+)&(?=[^<]+<)', '&amp;' } # escape & in text nodes
| % { $_ -replace 'href="mailto:.*?"', '' } # remove mailto links
| % { $_ -replace '(?<=<.+) [\w-]+=[\w-]+(?=.+>)', '' } # remove attributes without quotes
| Select-String $exp -AllMatches
| % { $_.Matches }
| % { $_.Groups[1].Value.Trim() }
| % { $_ -replace '<a .*?href="(.*?)"(?:.|\n)*', '$1'}
if($response.Count % 4 -ne 0) {
Write-Error "Unexpected number of download links: $($response.Count)"
}
$versionsCount = $response.Count / 4
Write-Host "Found $($versionsCount) download links"
$versions = @()
for($i = 0; $i -lt $versionsCount; $i++) {
$versions += [PSCustomObject]@{
Arch = $response[$i * 4 + 0]
Android = $response[$i * 4 + 1]
Dpi = $response[$i * 4 + 2]
Link = $response[$i * 4 + 3]
}
}
$filteredVersions = $versions
| Where-Object { $_.Arch -in $arch }
| Where-Object { $_.Dpi -eq $dpi }
if($filteredVersions.Count -eq 0) {
Write-Error "No matching APK found for arch=$arch and dpi=$dpi"
}
return $filteredVersions[0].Link
}
Function Get-Apk-Final-Download-Url($apkDownloadPageUrl) {
$url = "https://www.apkmirror.com$apkDownloadPageUrl"
$exp = '(?<=<a rel="nofollow" class="accent_bg btn btn-flat downloadButton ..." href=")(.+?)(?=">)'
return Invoke-WebRequest -Uri $url
| % { $_.Content }
| Select-String -Pattern $exp -AllMatches
| % { $_.Matches }
| % { $_.Groups[1].Value.Trim() }
}
Function Download-Apk($app, $version) {
$apkDownloadPageUrl = Get-Apk-Version-Arch-Dpi-Url $app $version
$finalUrl = "https://www.apkmirror.com$(Get-Apk-Final-Download-Url $apkDownloadPageUrl)"
$exp = '/wp-content/themes/APKMirror/download.php\?id=.+&key=.+&forcebaseapk=true'
$url = Invoke-WebRequest -Uri $finalUrl
| % { $_.Content }
| Select-String -Pattern $exp -AllMatches
| % { $_.Matches }
| % { $_.Groups[0].Value.Trim() }
$finalDownloadUrl = "https://www.apkmirror.com$url"
Invoke-WebRequest -Uri $finalDownloadUrl -OutFile $app.apkPath
Write-Host "Downloaded APK to $($app.apkPath)"
}
Function Patch-Apk($app) {
$Host.UI.RawUI.ForegroundColor = 'Gray'
& java -jar $cliPath patch -p $patchesPath -o $app.patchedApkPath $app.apkPath
[Console]::ResetColor()
Write-Host "Patched APK to $($app.patchedApkPath)"
}
Function Upgarde-App($app) {
Write-Host "Uninstalling old version"
& adb uninstall $app.revancedPackage # TODO: requires fixing, sometimes
Write-Host "Installing patched APK"
& adb install $app.patchedApkPath # TODO: requires fixing, sometimes
Write-Host "Upgraded"
}
Function Main() {
Write-Host "Using temporary directory $tmpDir"
Download-RevancedCli
Download-Patches
ForEach ($app in $apps) {
Write-Host "=============================="
Write-Host "Processing app $($app.package)"
Write-Host "=============================="
$versions = Get-Apk-Versions $app
$version = Select-Apk-Version $versions $app
if(-not $version) {
Write-Host "No version selected, skipping"
continue
}
Download-Apk $app $version
Patch-Apk $app
Upgarde-App $app
}
Remove-Item $tmpDir -Recurse -Force
}
$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment