CSV to JPG API
Send a comma-separated file to /v2/convert/csv/to/jpg and each printed page comes back as a JPEG. The sample sends FitToPage=true and ImageQuality=80: all ten weather columns shrink onto one A4 page, 1240 × 1753 pixels and 161,912 bytes.
- Endpoint
- POST /v2/
convert/ csv/ to/ jpg - Accepts
- csv
- Sample timing
- 0.76 s median of 5 runsHow we measure
- Request size
- Up to 10 MB on the Free plan or 100 MB on paid plans, all files together
Request and response
Every sample below ran against the API before this page was published. Set PDFCONVERSIONAPI_KEY to your key and run it as is.
curl -sS -X POST \
https://api.pdfconversionapi.com/v2/convert/csv/to/jpg \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@rooftop-weather-oct-2026.csv \
--form-string FitToPage=true \
--form-string ImageQuality=80 \
-o response.json
# FileData is base64. Save the first file in converted/,
# or print the JSON error.
if jq -e '.Files' response.json > /dev/null; then
mkdir -p converted
name=$(jq -r '.Files[0].FileName' response.json)
jq -r '.Files[0].FileData' response.json \
| base64 --decode > "converted/$name"
else
cat response.json
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/csv/to/jpg",
headers={"Authorization": f"Bearer {key}"},
files=[
("File", open("rooftop-weather-oct-2026.csv", "rb")),
],
data={
"FitToPage": "true",
"ImageQuality": "80",
},
timeout=180,
)
result = response.json()
if not response.ok:
raise SystemExit(f"{result['Code']}: {result['Message']}")
os.makedirs("converted", exist_ok=True)
for file in result["Files"]:
path = os.path.join("converted", file["FileName"])
with open(path, "wb") as out:
out.write(base64.b64decode(file["FileData"]))
print(path, file["FileSize"], "bytes")
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
const form = new FormData();
const file = "rooftop-weather-oct-2026.csv";
form.append("File", new Blob([await readFile(file)]), file);
form.append("FitToPage", "true");
form.append("ImageQuality", "80");
const url = "https://api.pdfconversionapi.com/v2/convert/csv/to/jpg";
const key = process.env.PDFCONVERSIONAPI_KEY;
const response = await fetch(url, {
method: "POST",
headers: { Authorization: `Bearer ${key}` },
body: form,
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${result.Code}: ${result.Message}`);
}
await mkdir("converted", { recursive: true });
for (const file of result.Files) {
const path = join("converted", file.FileName);
await writeFile(path, Buffer.from(file.FileData, "base64"));
console.log(path, file.FileSize, "bytes");
}
{
"ConversionCost": 1,
"ConversionTime": 0.76,
"Files": [
{
"FileName": "rooftop-weather-oct-2026-1.jpg",
"FileExt": "jpg",
"FileSize": 161912,
"FileData": "/9j/4AAQSkZJRgABAgAAAQAB…"
}
]
}Response from our test run on 2026-11-03. ConversionTime shows the median of 5 runs. FileData is shortened here; the real response carries the whole file as base64.
The sample, converted
The same file the code sends. Download the input and the output and compare them yourself.

- Input
- rooftop-weather-oct-2026.csv (1.8 KB)
- Output
- rooftop-weather-oct-2026-1.jpg (158 KB)
- Source
- Written for this site: a fictional rooftop weather station's daily readings for October 2026, saved as comma-separated UTF-8 with a formula row at the bottom (CC0-1.0). How it was made
- Made by
- 2026-11-04, API build
9eeeb0640aba
Parameters
Send these as form fields next to the file. Names are case-insensitive. If you set one of the documented options below that we don't support yet, the request fails with a 400 that names it instead of returning a file made without it.
| Parameter | What it does |
|---|---|
FitToPageboolean, default false | Scales the table down to one page wide. The sample uses it, so the Pressure and Observer note columns stay on page 1 instead of starting a second JPEG. |
ImageQualityinteger, default 85 | JPEG compression. Page 1 of the default printout weighs 147,971 bytes at 50, 214,191 at the default 85 and 417,698 at 100.Values: 1–100 |
ImageResolutioninteger, default 150 | Drawing resolution in pixels per inch; an A4 page is 1240 × 1753 at 150. When you send it, the JPEG's JFIF header records it too.Values: 36–600 |
PageOrientationenum, default default | landscape gives a wide page, 1169 × 826 at 100 DPI on A4.Values: default, portrait, landscape |
PageSizeenum, default default | Paper for the printout; with default, a CSV prints on A4.Values: letter, legal, tabloid, ledger, statement, executive, lettersmall, a3, a4, a4small, a5, b4, b5 |
Scaleinteger | Fixed print zoom in percent, as an alternative to FitToPage. At 70 the sample still takes two pages.Values: 10–300 |
HeaderOnEachPageboolean, default false | Prints the first CSV line again at the top of each later page, for files longer than one page. |
PageRangestring | Which printed pages to encode. The file name keeps the page number.Values: e.g. 1 or 2-last |
ImageWidthinteger | Target width in pixels; the page is drawn at that size rather than shrunk afterwards.Values: 1–20000 |
ImageHeightinteger | Target height in pixels, with the width following the paper's proportions.Values: 1–20000 |
BackgroundColorstring, default white | Paints the paper before the table is drawn on it.Values: a color name, #RRGGBB or R,G,B |
ColorSpaceenum, default default | gray writes a one-channel grayscale JPEG; cmyk is refused with 400.Values: rgb, gray, monochrome |
FileNamestring | Stem for the page files, followed by -1.jpg, -2.jpg and so on. |
StoreFileboolean, default false | Returns download links that stay valid for 3 hours instead of base64 data. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
Delimiter | Only commas separate fields. |
Also refused when set: AutoFitColumns, ThousandsSeparator, DecimalSeparator, DateFormat.
What carries over, and what doesn't
Kept
- Every row and all ten columns of the sample on one page, because of FitToPage
- Calculated formula results in the Month row: 65.3, 52.6, 18, 29 and 3.52
- The "°F" headings and the quoted notes that contain commas
- Dates as written (2026-10-01), right-aligned like numbers
Lost or not yet supported
- Exact pixels. JPEG is lossy: zoomed in, page 1 at quality 50 shows faint noise around the letters. The sample uses 80.
- Zeros after the decimal point: rain of 0.00 prints as 0 and 0.10 as 0.1.
- The file name. The page header says "input", in a serif face once any page option is sent.
- Transparency. JPEG has no alpha channel, and
TransparentColoris ignored for this output. - The DPI, unless you send
ImageResolution; the sample's JPEG stores none.
Limits
- One CSV per request. Sending two files returns 400.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- At most 2,000 pages are encoded per request.
- A page image may not exceed 16,000 pixels per side or 100,000,000 pixels (413).
- 120 seconds per conversion, then 504.
Where teams use it
A report people can read on a phone
Email clients and messaging apps open a JPEG inline. Send the morning's CSV export as one page image to people who never open attachments.
Previews for uploaded CSV files
Show a thumbnail of a user's upload in a file list. PageRange=1 with ImageWidth=400 gives a small preview of page one.
Wide logs on a single image
With FitToPage=true, a log with many columns stays one image wide instead of splitting its last columns onto a second picture.
Questions
How do I fit a wide CSV on one JPEG?
Send FitToPage=true. The table is scaled until it is one page wide, which is how the sample keeps all ten columns on page 1. PageOrientation=landscape also works for this file, with larger text.
Which ImageQuality should I use?
The default is 85. For page 1 of the sample's default printout we measured 147,971 bytes at 50, 214,191 at 85 and 417,698 at 100. Zoomed in, the quality 50 page shows faint noise around the letters.
Does a CSV with Windows line endings or a byte order mark work?
Yes. A copy of the sample saved with CRLF line endings and a UTF-8 byte order mark gave pixel-identical pages. The text must be UTF-8, though: in a Windows-1252 test file, José and Café printed with replacement marks. Files split by semicolons or tabs also need rewriting with commas, since Delimiter values other than a comma return 400.
Convert your first CSV file in a minute.