Table of Contents
Download a File Using Windows PowerShell
If you find yourself constantly clicking links to download files from the web, automating this task can be a significant time-saver. For those whose work involves frequent file downloads, consider utilizing PowerShell as an efficient alternative to the traditional wget command for downloading files.
Windows PowerShell and PowerShell are equipped with file-download capabilities. Downloading files using PowerShell involves understanding the appropriate cmdlets and .NET classes, as well as their application.
In this article, we will show you the various ways to use PowerShell to download files from the internet.
Prerequisites
Before you begin, there are some prerequisites to ensure that you can follow the examples. Below are the basic requirements.
- A computer that is running on Windows 10 or higher. This computer is where you will run the scripts/commands featured in this article. Windows PowerShell 5.1 or PowerShell 7.1 (recommended). Windows 10 already includes Windows PowerShell 5.1.
- A website that hosts the files to download. For non-authenticated file downloads, consider using the Tele2 Speedtest site, which is free. If you want to test file downloads with authorization, you may have to build your HTTP file server.
There are four methods to use PowerShell to download files that do not depend on third-party tools. These are:
- Invoke-WebRequest
- Invoke-RestMethod
- Start-BitsTransfer
- .NET WebClient
Regardless of which of the four methods you choose, the underlying logic and components remain consistent. You will need a source URL that directs to the file’s location and a destination path where the downloaded files will be saved. If the webserver demands it, credentials must also be provided. The following sections will detail each method. Ultimately, the choice of which method to adopt for downloading files using PowerShell is yours.
Using Invoke-WebRequest as a PowerShell wget Alternative
The initial method for downloading files in PowerShell involves using the Invoke-WebRequest cmdlet. This cmdlet, possibly the most utilized in this context, is capable of downloading files from HTTP, HTTPS, and FTP links.
The syntax provided below outlines the minimum parameters necessary to download a file successfully.
Invoke-WebRequest -Uri <source> -OutFile <destination>
For example, the code below downloads a file with the name 10MB.zip from a source. Then it saves the downloaded file to D:\Temp\10MB.zip. You may copy the code below and paste it into your PowerShell session to test.
# Source file location
$source = 'http://speedtest.tele2.net/10MB.zip'
# Destination to save the file
$destination = 'D:\Temp\10MB.zip'
# Download the file
Invoke-WebRequest -Uri $source -OutFile $destination
The demonstration below shows the expected result after running the code above in PowerShell. As you can see, the file download was successful.
The file 10MB.zip is downloaded to D:\Temp\10MB.zip.
The source requires authentication
How about if the source requires authentication before allowing access? For example, the code below downloads a file from a private website where users must log in. Whether the source location requires users to log in, the Invoke-WebRequest cmdlet can handle requests with credentials as well.
If authentication is required, you should add a credential to the request using the –Credential parameter. The first line in the code below prompts you to enter the credential (username and password) and stores it to the $credential variable.
$credential = Get-Credential
$source = 'http://downloads.bonguides.com/10MB.zip'
$destination = 'D:\Downloads\10MB.zip'
Invoke-WebRequest -Uri $source -OutFile $destination -Credential $credential
The demonstration below shows what you’d expect to see when you run the above code in PowerShell. As you can see, the Get-Credential cmdlet prompted a PowerShell credential request. This time, using the credential with Invoke-WebRequest resulted in a successful download.
After authenticated to the source, the file should be downloaded automatically.
If you don’t want to enter the credentials manually. You can pre-declare them into the script as the variables.
# URL and Destination
$source = 'http://downloads.bonguides.com/10MB.zip'
$destination = 'D:\Downloads\10MB.zip'
# Define username and password
$username = 'test'
$password = '123'
# Convert to SecureString
$secPassword = ConvertTo-SecureString $password -AsPlainText -Force
# Create Credential Object
$credObject = New-Object System.Management.Automation.PSCredential ($username, $secPassword)
# Download file
Invoke-WebRequest -Uri $source -OutFile $destination -Credential $credObject
Download multiple files
In case you want to download multiple files. You can put the URLs of the files into a hashtable. Then use the PowerShell foreach loop to download them in sequence.
$hashtable = @{
'http://speedtest.tele2.net/1MB.zip' = 'D:\temp\1MB.zip'
'http://speedtest.tele2.net/5MB.zip' = 'D:\temp\5MB.zip'
'http://speedtest.tele2.net/10MB.zip' = 'D:\temp\10MB.zip'
}
ForEach ($file in $hashtable.GetEnumerator()) {
Invoke-WebRequest -Uri $file.Key -OutFile $file.Value
}
Using Invoke-RestMethod
The Invoke-RestMethod cmdlet is more about sending an HTTP or HTTPS request to a RESTful web service. This cmdlet is more suited for requests that interact with REST APIs such as Microsoft Graph API.
When downloading files directly from the web, Invoke-RestMethod is a strong option. Don’t be misled; there’s little difference between using Invoke-RestMethod and Invoke-WebRequest for downloading files from a direct web link.
To download a file using Invoke-RestMethod, use the syntax below. You’ll notice that the command uses the same parameters as Invoke-WebRequest.
Invoke-RestMethod -Uri <source> -OutFile <destination>
In the example code below, the file is downloaded from the URL value in the $source variable. Then, saved to the path defined in the $destination variable.
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'D:\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $destination
If the source requires authentication, you can pass the credentials using the -Credential parameter. Also, since the file link is an HTTP source and not HTTPS, it means that you are sending an unencrypted authentication. Typically, you should avoid using HTTP sources for security. But if you must use an HTTP source, you need to add the -AllowUnencryptedAuthentication switch to your command.
$cred = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$dest = 'D:\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $dest -Credential $cred -AllowUnencryptedAuthentication
Using Start-BitsTransfer
Start-BitsTransfer is designed specifically for transferring files between client and server computers. This PowerShell cmdlet is dependent on the Background Intelligent Transfer Service (BITS) that is native to the Windows operating system.
Because Start-BitsTransfer requires BITS to work means that this cmdlet is not available on non-Windows computers. On the flipside, Start-BitsTransfer enjoys the benefits of BITS itself. Some of these benefits are:
- Network bandwidth and usage awareness.
- Interruption handling (resume, auto-resume, pause, etc.)
- Downloading multiple files as background jobs.
- Ability to set download job priorities.
The basic method for downloading a file with Start-BitsTransfer in PowerShell involves defining a source and a destination. In the script provided, simply adjust the $source and $destination variables to fit your needs.
$source = 'http://speedtest.tele2.net/10MB.zip'
$dest = 'D:\10MB.zip'
Start-BitsTransfer -Source $source -Destination $dest
Download as a job
If you wish to initiate the download process as a background task, simply append the -Asynchronous switch to the end of the Start-BitsTransfer command.
$source = 'http://speedtest.tele2.net/10MB.zip'
$dest = 'D:\10MB.zip'
Start-BitsTransfer -Source $source -Destination $dest -Asynchronous
# Output
$PS C:\> Start-BitsTransfer -Source $source -Destination $dest -Asynchronous
JobId DisplayName TransferType JobState OwnerAccount
----- ----------- ------------ -------- ------------
17f96cd0-bb92-4e89-b074-6a5119bb1ea0 BITS Transfer Download Connecting DESKTOP-B2TOHJT\admin
Now that the download process has begun, you may want to verify if it has completed. To check the status of the download job, utilize the Get-BitsTransfer cmdlet. As indicated below, the status of the download jobs has changed to ‘Transferred’.
PS C:\> Get-BitsTransfer
JobId DisplayName TransferType JobState OwnerAccount
----- ----------- ------------ -------- ------------
17f96cd0-bb92-4e89-b074-6a5119bb1ea0 BITS Transfer Download Transferred DESKTOP-B2TOHJT\admin
If you want to download multiple files. Use a hastable and foreach loop.
$hashtable = @{
'http://speedtest.tele2.net/1MB.zip' = 'D:\temp\1MB.zip'
'http://speedtest.tele2.net/5MB.zip' = 'D:\temp\5MB.zip'
'http://speedtest.tele2.net/10MB.zip' = 'D:\temp\10MB.zip'
}
ForEach ($file in $hashtable.GetEnumerator()) {
Start-BitsTransfer -Source $file.Key -Destination $file. Value
}
Using WebClient Class and HttpClient Class (.NET Framework)
PowerShell is built on .NET, which enables it to harness the capabilities of .NET itself. There are two .NET classes that can be utilized in PowerShell for downloading files: WebClient and HttpClient.
Using WebClient Class
To utilize the WebClient class, you must create an instance of the System.Net.WebClient type. For instance, in the code below, the $webClient variable represents the newly instantiated System.Net.WebClient object. You then initiate the file download from the source using the DownloadFile() method.
Please copy the code below and run it in your PowerShell session to test. Note that you will not see any progress or output on the screen unless there’s an error. However, the PowerShell prompt will be locked until the download is complete.
# Define the source link and destination path
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'D:\temp\1MB.zip'
# Create the new WebClient
$webClient = [System.Net.WebClient]::new()
# Download the file
$webClient.DownloadFile($source, $destination)
If the source requires authentication to allow the file download, you can use the code below. The first line prompts for the credential and stores it to the $credentials variable. The value of $credential is then included in the file download request.
# Prompt for username and password
$credentials = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'D:\temp\1MB.zip'
# Create the new WebClient
$webClient = [System.Net.WebClient]::new()
# Add the credential
$webClient.Credentials = $credentials
# Download the file
$webClient.DownloadFile($source, $destination)
Again, the credential can be included into the script to bypass credentials prompt when downloading.
# URL and Destination
$url = 'http://downloads.bonguides.com/10MB.zip'
$dest = 'D:\Downloads\10MB-005.zip'
# Define username and password
$username = 'test'
$password = '123'
# Convert to SecureString
$secPassword = ConvertTo-SecureString $password -AsPlainText -Force
# Create Credential Object
$credObject = New-Object System.Management.Automation.PSCredential ($username, $secPassword)
# Download file
Invoke-WebRequest -Uri $url -OutFile $dest -Credential $credObject
Using the HttpClient class
Microsoft doesn’t recommend that you use the WebClient class for new development. Instead, use the System.Net.Http.HttpClient class for better capability.
Similar to the WebClient class, you must first instantiate the System.Net.Http.HttpClient. The following code snippet facilitates downloading a file from the specified $source to the $destination. Please refer to the comments preceding each line for an explanation of what each line accomplishes.
The code below is live, and you can test it by running it in your PowerShell session:
# Set the source and destination
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'D:\temp\10MB.zip'
# Load the required assembly
Add-Type -AssemblyName System.Net.Http
# Create the HTTP client download request
$httpClient = New-Object System.Net.Http.HttpClient
$response = $httpClient.GetAsync($source)
$response.Wait()
# Create a file stream to pointed to the output file destination
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
# Stream the download to the destination file stream
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
# Close the file stream
$outputFileStream.Close()
When downloading a file necessitates authentication, it’s necessary to append the credentials to the HttpClient object. To incorporate credentials into the file download request, instantiate a new System.Net.Http.HttpClientHandler object designed to hold the credentials.
You can copy the code below and run it in PowerShell to test. Or you can also run it as a PowerShell script.
# Set the source and destination
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'D:\temp\10MB.zip'
# Load the required assembly
Add-Type -AssemblyName System.Net.Http
# Prompt for credentials
$credentials = Get-Credential
# Create the HTTP client download request with credentials
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.Credentials = $credentials
$httpClient = New-Object System.Net.Http.HttpClient($handler)
$response = $httpClient.GetAsync($source)
$response.Wait()
# Create a file stream to pointed to the output file destination
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
# Stream the download to the destination file stream
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
# Close the file stream
$outputFileStream.Close()
Conclusion
Windows PowerShell and PowerShell Core are equipped with built-in features for downloading files, serving as an alternative to wget in PowerShell. Whether it’s downloading from password-protected sources or handling single or multiple files, there’s a PowerShell method suited for the task.
The file download techniques discussed in this article are compatible with both Windows PowerShell and PowerShell Core. Consequently, these techniques are applicable to systems running Windows as well as non-Windows operating systems, except for the Start-BitsTransfer command.
PowerShell extends beyond a simple command prompt; it allows you to convert your knowledge into scripts. This presents an opportunity for automation, eliminating the need to manually copy URLs, click links, and wait for downloads.
Not a reader? Watch this related video tutorial: