PowerShell ConvertFrom-Csv: Parse CSV Text Without a File

Some APIs return CSV-formatted text in an HTTP response body rather than JSON. Legacy tools output comma-separated data you need to process. PowerShell ConvertFrom-Csv parses CSV-formatted strings directly into objects without needing to write the data to a file first. This post covers how to use it for API responses, command output, and in-memory data transformation.
Quick Answer / TL;DR
Pipe a CSV string to ConvertFrom-Csv to get objects. Use -Header when the first row is data (no header row). Use -Delimiter for non-comma separators.
Basic ConvertFrom-Csv Usage
ConvertFrom-Csv reads the first row as column headers and subsequent rows as values, converting each row into a PSCustomObject. The input can be a single multiline string or an array of strings — one string per CSV row.
# Parse a CSV string with headers
$csvData = @"
Name,Department,Email
John Smith,IT,[email protected]
Jane Doe,Finance,[email protected]
Bob Wilson,HR,[email protected]
"@
$users = $csvData | ConvertFrom-Csv
$users | Format-Table -AutoSize
Name Department Email
---- ---------- -----
John Smith IT [email protected]
Jane Doe Finance [email protected]
Bob Wilson HR [email protected]
Specify Custom Headers
When the CSV data has no header row — just raw data — use -Header to supply column names. Without it, the first data row becomes the property names, which is usually wrong for headerless files.
# Data without a header row
$rawData = @"
jsmith,John Smith,IT,[email protected]
jdoe,Jane Doe,Finance,[email protected]
"@
# Supply headers explicitly
$users = $rawData | ConvertFrom-Csv -Header 'SamAccountName','DisplayName','Department','Email'
# Now properties are correctly named
$users | Where-Object Department -eq 'IT' | Select-Object SamAccountName, Email
Parse API CSV Response
When an API returns CSV text in the response body, use Invoke-RestMethod or Invoke-WebRequest to fetch the data, then pipe directly to ConvertFrom-Csv. This is cleaner than writing to a temp file and using Import-Csv.
# API that returns CSV content-type
$response = Invoke-WebRequest -Uri 'https://api.example.com/export/users' -UseDefaultCredentials
$csvText = $response.Content
$users = $csvText | ConvertFrom-Csv
# Filter and process in-memory
$activeUsers = $users | Where-Object Status -eq 'Active'
Write-Host "Active users: $($activeUsers.Count)"
$activeUsers | Export-Csv C:\Reports\active_users.csv -NoTypeInformation
Convert Command Output to CSV Objects
Some command-line tools output CSV-formatted text. Capture the output, skip any non-CSV header lines, then pipe to ConvertFrom-Csv to get usable objects.
# wmic output is tab-separated — use -Delimiter
$wmicOutput = wmic process get Name,ProcessId,WorkingSetSize /FORMAT:CSV 2>$null |
Where-Object { $_ -and $_ -notmatch '^Node' }
$processes = $wmicOutput | ConvertFrom-Csv
$processes |
Where-Object { [long]$_.WorkingSetSize -gt 100MB } |
Select-Object Name, ProcessId, @{N='RAM_MB';E={[math]::Round([long]$_.WorkingSetSize/1MB,1)}} |
Sort-Object RAM_MB -Descending |
Format-Table -AutoSize
ConvertFrom-Csv vs Import-Csv
The functional difference is simple: Import-Csv reads from a file on disk; ConvertFrom-Csv reads from a string in memory. Both produce identical PSCustomObject output with the same property access and pipeline behavior. Use Import-Csv when data is in a file, ConvertFrom-Csv when data is in a variable or pipeline string.
# These produce equivalent results
$fromFile = Import-Csv -Path C:\Data\users.csv
$fromString = Get-Content -Path C:\Data\users.csv -Raw | ConvertFrom-Csv
# Verify they are equivalent
$fromFile.Count -eq $fromString.Count
$fromFile[0].Name -eq $fromString[0].Name
Pipeline Chain Example
A complete pipeline that fetches CSV from a URL, filters, transforms, and exports — all without writing any intermediate files.
$reportData = (Invoke-WebRequest -Uri 'https://reports.contoso.com/api/monthly.csv').Content |
ConvertFrom-Csv |
Where-Object { [int]$_.Amount -gt 1000 } |
Select-Object Date, Category,
@{N='Amount'; E={[int]$_.Amount}},
@{N='Formatted'; E={ '$' + '{0:N2}' -f [int]$_.Amount }}
$reportData | Export-Csv C:\Reports\high_value.csv -NoTypeInformation
Write-Host "Exported $($reportData.Count) high-value records"
Common Errors and Fixes
- No header row in input — must specify -Header parameter. If your CSV data has no first-row headers and you omit
-Header, the first data row becomes the property names. You lose one record and property names are meaningless data values. Always add-Headerwhen working with headerless CSV data. - Custom delimiter needed for semicolon-separated data. European locale CSV files often use semicolons as delimiters. Pass
-Delimiter ';'toConvertFrom-Csv. Tab-separated data uses-Delimiter "`t"(backtick-t for the tab character in PowerShell strings).
Related Cmdlets / See Also
Wrapping Up
ConvertFrom-Csv is the in-memory counterpart to Import-Csv. Use it when your CSV data arrives as a string from an API, command output, or variable. It produces the same objects as Import-Csv, integrates with the full pipeline, and eliminates the need for intermediate temp files when processing CSV data in memory.


