Gracefully shutdown Qbit via Powershell?

Windows specific questions, problems.
Post Reply
Sandpaper0724
Newbie
Newbie
Posts: 2
Joined: Sat Mar 29, 2025 11:26 pm

Gracefully shutdown Qbit via Powershell?

Post by Sandpaper0724 »

I've searched far and wide and haven't had any luck with this yet.

Right now, PIA is randomly assigning me a new port 5 -10 times per day. It's a pain to have to go in, get the new port, open connection settings, and enter it over, and over, and over.

i found a script that will check if the ports match, kill the qbit task if not, rewrite the port and relauch qbit but that results in torrents showing as missing files since it's a task kill and not a graceful shutdown. If i shut down and relauch qbit manually, I don't have that issue. I see there's a shutdown in the Qbit WebUI API but i keep getting a 503 Forbidden error.

Does anyone know how to actually get Qbit to shut down gracefully via an API call?

Here's what i've got so far:

# Create a session to store cookies
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession

# Authenticate and capture cookies
$loginResponse = Invoke-WebRequest -Uri "$QB_URL/api/v2/auth/login" `
-Method Post `
-Body @{username=$USERNAME; password=$PASSWORD} `
-UseBasicParsing `
-WebSession $session

# Check if login was successful
if ($loginResponse.Content -match "Ok") {
Write-Output "Login successful. Shutting down qBittorrent..."

# Send shutdown command using POST instead of GET
try {
$shutdownResponse = Invoke-WebRequest -Uri "$QB_URL/api/v2/app/shutdown" `
-Method Post ` # <-- Changed to POST
-WebSession $session `
-UseBasicParsing

Write-Output "Shutdown command sent successfully."
} catch {
Write-Output "Failed to send shutdown command. Status Code: $($_.Exception.Response.StatusCode)"
}
} else {
Write-Output "Login failed. Please check your credentials and WebUI settings."
}
Sandpaper0724
Newbie
Newbie
Posts: 2
Joined: Sat Mar 29, 2025 11:26 pm

Re: Gracefully shutdown Qbit via Powershell?

Post by Sandpaper0724 »

Well, I can answer my own question:

I was able to include CSRF headers in the script and got it to accept the WebUI API shutdown command. This script will check the port from PIA and compare it to the port in qbit. If they don't match, it will gracefully shut down Qbit, write the correct port, and relaunch qbit 120 seconds later.

# Configuration for qBittorrent WebUI API
$QB_URL = "http://localhost:8080" # Change if qBittorrent runs on a different IP/port
$USERNAME = "admin" # Change to your WebUI username
$PASSWORD = "adminadmin" # Change to your WebUI password
$qbit_ini = "C:\Users\Jake\AppData\Roaming\qBittorrent\qBittorrent.ini"

# Get current qBittorrent port
$qbit_port = Select-String -Path $qbit_ini 'Session\\Port=\d*' | Select-Object -ExpandProperty Line
$qbit_port = $qbit_port -creplace '^[^0-9]*'
$qbit_process = Get-Process qbittorrent -ErrorAction SilentlyContinue

# Get PIA assigned port
$pia_port = & "C:\Program Files\Private Internet Access\piactl.exe" get portforward
$pia_port = $pia_port -as [int]

if ($qbit_port -ne $pia_port) {
if ($qbit_process) {
Write-Output "PIA port updated, need to update qBittorrent!"
Write-Output "Shutting down qBittorrent gracefully..."

# Create a session to store cookies
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession

# Authenticate and capture cookies
$loginResponse = Invoke-WebRequest -Uri "$QB_URL/api/v2/auth/login" `
-Method Post `
-Body @{username=$USERNAME; password=$PASSWORD} `
-UseBasicParsing `
-WebSession $session

if ($loginResponse.Content -match "Ok") {
Write-Output "Login successful. Sending shutdown request..."

try {
# Send shutdown command using POST
$headers = @{
"Content-Type" = "application/x-www-form-urlencoded"
"Referer" = $QB_URL
}

$shutdownResponse = Invoke-WebRequest -Uri "$QB_URL/api/v2/app/shutdown" `
-Method Post `
-Headers $headers `
-WebSession $session `
-UseBasicParsing

Write-Output "Shutdown command sent successfully."
} catch {
Write-Output "Failed to send shutdown command. Status Code: $($_.Exception.Response.StatusCode) - $($_.ErrorDetails.Message)"
}
} else {
Write-Output "Login failed. Please check your credentials and WebUI settings."
}

# Wait for qBittorrent to fully close
Start-Sleep -Seconds 30

# Update qBittorrent config
Write-Output "Updating qBittorrent config..."
(Get-Content $qbit_ini) -replace "Session\\Port=\d*", "Session\Port=$pia_port" | Set-Content -Path $qbit_ini
Start-Sleep -Seconds 1

# Start qBittorrent again
Write-Output "Starting qBittorrent..."
Start-Process -FilePath "J:\Program Files\qBittorrent\qbittorrent.exe"
Start-Sleep -Seconds 5

# Verify qBittorrent restarted
$qbit_process = Get-Process qbittorrent -ErrorAction SilentlyContinue
if ($qbit_process) {
$qbit_process.CloseMainWindow()
Write-Output "qBittorrent started! Exiting..."
} else {
Write-Output "qBittorrent not started yet. Waiting..."
Start-Sleep -Seconds 10
$qbit_process = Get-Process qbittorrent -ErrorAction SilentlyContinue
if ($qbit_process) {
$qbit_process.CloseMainWindow()
Write-Output "qBittorrent started! Exiting..."
} else {
Write-Output "Failed to start qBittorrent!"
}
}
}
} else {
Write-Output "Ports match, nothing to do..."
}
Post Reply