Invoke-WebRequest: descargar archivos y probar URLs en PowerShell

Invoke-WebRequest: descargar archivos y probar URLs en PowerShell

El servidor de actualización de los agentes de endpoint dejó de responder en un Patch Tuesday. El equipo de infraestructura necesitaba comprobar si la dirección estaba accesible, descargar el instalador manualmente y validar el hash SHA256 — todo esto en un servidor core sin interfaz gráfica. Tres cmdlets de PowerShell lo resolvieron en menos de dos minutos.

¿Qué es Invoke-WebRequest?

El Invoke-WebRequest es el cmdlet de PowerShell que hace solicitudes HTTP y HTTPS — el equivalente a curl en Linux o a wget. Devuelve un objeto con el código de estado, los headers de la respuesta, las cookies y el contenido. Está disponible desde PowerShell 3.0 en Windows y en PowerShell 7+ en cualquier plataforma.

¿Cuál es la diferencia entre Invoke-WebRequest e Invoke-RestMethod?

Invoke-WebRequest devuelve el objeto HTTP completo — estado, headers y contenido bruto. Invoke-RestMethod parsea la respuesta JSON o XML automáticamente y devuelve un objeto de PowerShell ya listo para usar. Para descargar archivos o comprobar la disponibilidad de URLs, usá Invoke-WebRequest. Para consumir APIs que responden en JSON, Invoke-RestMethod es más directo.

Descargar un archivo con PowerShell

El caso de uso más frecuente: descargar un ejecutable, script o archivo de configuración directo desde la terminal, sin abrir el navegador.

Invoke-WebRequest -Uri "https://ejemplo.com/patch.msi" -OutFile "C:\Downloads\patch.msi"

El parámetro -OutFile guarda el contenido en la ruta especificada. Sin él, el contenido va a la salida estándar — útil para procesar en memoria, pero ineficiente para archivos grandes.

En scripts de automatización, desactivá la barra de progreso para ganar velocidad — consume CPU innecesariamente cuando no hay interfaz interactiva:

$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri "https://ejemplo.com/instalador.exe" -OutFile "C:\Temp\instalador.exe"
$ProgressPreference = 'Continue'

Después de la descarga, validá la integridad del archivo con el hash SHA256 antes de ejecutar cualquier cosa:

Get-FileHash -Path "C:\Temp\instalador.exe" -Algorithm SHA256

Compará el hash devuelto con el valor publicado por el proveedor. Si no coincide, el archivo está corrupto o alterado — descartalo y descargalo de nuevo.

Verificar si una URL está accesible

¿Cómo saber si un sitio o servicio web está activo usando PowerShell?

Usá Invoke-WebRequest con -UseBasicParsing dentro de un bloque try/catch: el código 200 significa que la URL responde, cualquier 5xx indica una falla en el servidor, y una excepción capturada indica timeout o error de DNS.

try {
    $response = Invoke-WebRequest -Uri "https://miservidor.empresa.com/health" `
        -UseBasicParsing -TimeoutSec 10
    Write-Host "Status: $($response.StatusCode)"
} catch {
    Write-Host "Falló: $_"
}

El parámetro -UseBasicParsing evita que el cmdlet intente procesar el HTML como DOM — necesario en servidores sin el motor de Internet Explorer (Windows Server Core, por ejemplo) y más eficiente en todos los casos.

Para monitorear varios endpoints a la vez:

$urls = @(
    "https://servidor1.empresa.com/ping",
    "https://servidor2.empresa.com/ping",
    "https://api-interna.empresa.com/v1/health"
)

foreach ($url in $urls) {
    try {
        $r = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5
        Write-Host "$url — $($r.StatusCode)"
    } catch {
        Write-Host "$url — ERROR: $($_.Exception.Message)"
    }
}

Este script se puede programar con schtasks para ejecutarse cada 5 minutos y guardar el resultado en un log — convirtiendo una prueba manual en monitoreo continuo.

Enviar headers y autenticación

Las APIs protegidas y los servidores que bloquean User-Agents genéricos exigen headers personalizados. El parámetro -Headers acepta una hashtable:

$headers = @{
    "Authorization" = "Bearer TU_TOKEN_AQUI"
    "Accept"        = "application/json"
    "User-Agent"    = "MonitorScript/1.0"
}

$response = Invoke-WebRequest -Uri "https://api.ejemplo.com/datos" `
    -Headers $headers -UseBasicParsing

Para autenticación básica con usuario y contraseña, usá Get-Credential — abre un prompt seguro sin exponer la contraseña en el script:

$cred = Get-Credential
Invoke-WebRequest -Uri "https://intranet.empresa.com/reporte" `
    -Credential $cred -UseBasicParsing

Consumir APIs REST con Invoke-RestMethod

Cuando la respuesta es JSON, Invoke-RestMethod la convierte automáticamente en un objeto de PowerShell — las propiedades quedan accesibles directamente con punto, sin necesidad de ConvertFrom-Json:

# Consulta la API pública de GitHub
$repo = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/PowerShell"
Write-Host "Stars: $($repo.stargazers_count)"
Write-Host "Actualizado el: $($repo.updated_at)"

Para una API interna de seguridad — un SIEM o plataforma de threat intel — el patrón es el mismo:

$alertas = Invoke-RestMethod -Uri "https://siem.empresa.com/api/alertas" -Headers $headers
$alertas | Where-Object { $_.severity -eq "critical" } | Select-Object title, timestamp

Alternativa para archivos grandes: BITS

El Invoke-WebRequest no soporta reanudación de descarga (pausar/reanudar). Para archivos grandes en conexiones inestables, el BITS (Background Intelligent Transfer Service) es más robusto:

Start-BitsTransfer -Source "https://ejemplo.com/archivo-grande.iso" `
    -Destination "C:\Downloads\archivo.iso"

BITS usa ancho de banda ocioso, reanuda automáticamente tras una interrupción y se integra con el programador de tareas de Windows — ideal para actualizaciones que no necesitan entrega inmediata.

Para instalaciones completas de software, winget gestiona descargas e instalaciones de paquetes en un único comando, sin necesidad de usar Invoke-WebRequest manualmente. Y para descargas recurrentes que necesitan sincronizarse en red, Robocopy complementa bien una vez que los archivos llegan localmente.

Conclusión

El Invoke-WebRequest resuelve tres problemas comunes sin abrir un navegador ni instalar herramientas extra: descargar archivos, verificar la disponibilidad de servicios y consumir APIs. El patrón try/catch con -TimeoutSec es lo que convierte una prueba manual en un script de monitoreo real. Para cruzar estos resultados con lo que está pasando en el sistema operativo, mirá cómo Get-WinEvent permite correlacionar fallas HTTP con errores registrados en los logs de Windows — una combinación útil en diagnósticos de servicios críticos.

Comentarios