PowerShell offers robust capabilities for downloading files from the web. The two primary cmdlets for this purpose are Invoke-WebRequest
and Start-BitsTransfer
.
Invoke-WebRequest
Invoke-WebRequest
sends HTTP and HTTPS requests, including those for downloading files. It is suitable for straightforward downloads.
Basic Download:

Invoke-WebRequest -Uri "YOUR_FILE_URL" -OutFile "C:pathtoyourlocal*"
This command downloads the file from the specified URI and saves it to the local path provided in -OutFile
.
Using Basic Parsing:
Invoke-WebRequest -Uri "YOUR_FILE_URL" -OutFile "C:pathtoyourlocal*" -UseBasicParsing
The -UseBasicParsing
parameter is recommended for scripts or when the Internet Explorer engine (used by default in older PowerShell versions) is not available or desired. In PowerShell 6 and newer, basic parsing is the default behavior.
Handling Timeouts:
You can specify a timeout in seconds using the -TimeoutSec
parameter. For no timeout, use -TimeoutSec 0
. For operations that might take longer, adjust accordingly.

Invoke-WebRequest -Uri "YOUR_FILE_URL" -OutFile "C:pathtoyourlocal*" -TimeoutSec 300
Start-BitsTransfer
The Background Intelligent Transfer Service (BITS) is designed for transferring files asynchronously, efficiently using idle network bandwidth, and can resume transfers after interruptions.
Prerequisite:
The BitsTransfer module may need to be imported, especially on older systems, though it often auto-loads.
Import-Module BitsTransfer
Asynchronous Download:
Start-BitsTransfer -Source "YOUR_FILE_URL" -Destination "C:pathtoyourlocal*"
This command initiates a BITS job. The download occurs in the background. You can monitor its progress with Get-BitsTransfer
.

Synchronous Download (Waiting for Completion):
To make the script wait until the BITS transfer is complete, you can pipe the job to Wait-BitsTransfer
and then Complete-BitsTransfer
.
Start-BitsTransfer -Source "YOUR_FILE_URL" -Destination "C:pathtoyourlocal*" Wait-BitsTransfer Complete-BitsTransfer
Alternatively, manage the job explicitly:
$BitsJob = Start-BitsTransfer -Source "YOUR_FILE_URL" -Destination "C:pathtoyourlocal*"
while ($* -in ("Queued", "Connecting", "Transferring")) { Start-Sleep -Seconds 5 }
Complete-BitsTransfer -BitsJob $BitsJob
Choosing the Right Cmdlet
-
Invoke-WebRequest
: Best for simpler, direct downloads where advanced features like background operation or automatic resumption are not critical. It's generally quicker for smaller files if the network is stable. -
Start-BitsTransfer
: Preferred for large files, downloads over unreliable networks, or when downloads need to occur in the background without impacting foreground tasks. Its ability to resume interrupted transfers is a significant advantage.
Error Handling
It is good practice to wrap download commands in try...catch
blocks to gracefully handle potential errors such as network issues, invalid URLs, or permissions problems.
Example with Invoke-WebRequest:
try {
Invoke-WebRequest -Uri "YOUR_INVALID_OR_VALID_URL" -OutFile "C:pathtoyourlocal*" -ErrorAction Stop
Write-Host "Download completed successfully."
catch {
Write-Error "Download failed: $($_.*)"
Using -ErrorAction Stop
within the try
block ensures that terminating errors are caught by the catch
block.