Turn a CSV into QR codes — one per row
Export your spreadsheet, upload it, and download a ZIP with a QR code for every row. Everything runs in your browser: your file is never uploaded to a server.
If you need fifty QR codes, making them one at a time is miserable. If you need five hundred, it is out of the question. The batch workflow here is built around the file you almost certainly already have: a spreadsheet. Any list of URLs, serial numbers, coupon codes, or asset tags that lives in Excel or Google Sheets can become a folder of print-ready QR codes in about a minute, and because the whole thing runs client-side, nothing in that spreadsheet ever touches a server.
How to convert a CSV to QR codes
- Export your sheet as CSV. In Google Sheets: File → Download → Comma-separated values. In Excel: File → Save As → CSV UTF-8. In Numbers: File → Export To → CSV. The first row should be column headers — for example url, name, sku.
- Open the generator and switch to the Batch Creation tab.
- Choose Upload CSV and pick your file. The row count appears immediately so you can confirm the file parsed correctly.
- Map your columns. Pick the data column (what each code encodes — usually the URL), and optionally a filename column and a label column.
- Click Generate. Codes render one by one with a progress bar; you can cancel at any point and keep what has finished.
- Download the ZIP. Every successful code is included as a PNG, named by your filename column or numbered sequentially.
Preparing a clean CSV
Most batch problems trace back to the file, not the generator. A two-minute check saves a reprint:
- Headers in row one. The column pickers are driven by your header names. If row one is data instead of headers, your first entry becomes a column name and disappears from the batch.
- UTF-8 encoding. Older Excel exports default to regional encodings that mangle accented characters. Use the “CSV UTF-8” option so café stays café.
- Full URLs. Rows like example.com/page will encode literally. Phones treat a QR payload without a scheme as plain text rather than a link, so include https:// in the sheet (a fill-down formula fixes a whole column in seconds).
- Commas and quotes inside values are fine. The parser handles standard CSV quoting — a URL with query parameters or a label like Table 12, Patio will not break the row.
- Watch for trailing blank rows. Spreadsheets love exporting a few empty lines at the bottom. Empty rows are skipped and reported, so they will not corrupt the batch, but the skipped count can be confusing if you are not expecting it.
Understanding the three column roles
| Column | Required | What it does |
|---|---|---|
| Data | Yes | The content each QR code encodes — a URL or any text. |
| Filename | No | Names each PNG inside the ZIP. Use an SKU, room number, or slug so the files sort meaningfully. Illegal filename characters are stripped automatically. |
| Label | No | A human-readable caption shown under each result in the browser, handy for spot-checking that row 37 really is the patio menu. |
If you skip the filename column, files are numbered in row order — fine for a one-off, painful when a print vendor asks which file goes on which product. For any batch that leaves your desk, name the files from a real identifier in the sheet.
Styling applies to the whole batch
Colors, output size, error-correction level, and an optional centered logo are set once in the Generator tab and applied to every code in the batch. That is deliberate: printed sets look professional when they are visually identical, and a single set of choices means a single scanability review instead of five hundred. If you need two visual styles — say, black codes for packaging and brand-purple codes for a brochure — run the batch twice with different settings. Batches are fast enough that this costs you a minute, not an afternoon. Applying a logo across a batch is available on paid plans; see the logo guide for how logo overlays affect scanability.
From ZIP to printed pieces
The ZIP is the handoff point to whatever produces the physical thing:
- Data-merge layouts. InDesign Data Merge and Canva Bulk Create can place images by filename. Because your PNGs are named from a spreadsheet column, the same sheet drives both the codes and the layout — one source of truth from spreadsheet to printed card.
- Print resolution math. A 1024×1024 PNG prints at 3.4 inches (8.6 cm) at 300 DPI, and a 512 px export covers anything up to 1.7 inches. For typical label and sticker sizes, 512 px is comfortably sharp; go 1024 px for posters.
- Test one before printing all. Print a single sheet at final size, scan it with two different phones, then commit the run. Every print professional has a story about the batch nobody test-scanned.
Batch limits by plan
The free tier generates up to 15 codes per batch — enough to trial the workflow end to end. Paid plans raise the cap: 25 on Personal and up to 500 per batch on Pro. There is no limit on the number of batches you run on any tier, and codes you have already generated never expire or stop working.
Troubleshooting
- “0 rows detected.” The file probably is not really a CSV — re-export rather than renaming an .xlsx to .csv.
- Codes encode the wrong thing. The data column mapping is pointed at the wrong header. Re-map and regenerate; nothing is saved server-side, so regenerating is free and instant.
- Some rows failed. Failed rows are shown individually with the reason (usually an empty value or content too long to encode). Fix those cells in the sheet and re-upload.
- Codes look dense and busy. Long URLs mean more modules and harder scanning at small sizes. Shorten the URLs — or use dynamic codes, which encode a short redirect link regardless of destination length.
- Special characters look wrong when scanned. Re-export as UTF-8; this is an encoding issue in the file, not the code.
Batch workflows people actually run
A few patterns come up constantly, and they are worth stealing:
- Equipment and asset tags. One row per asset, the data column pointing at that asset’s maintenance page or record, the filename column set to the asset ID. The ZIP feeds a label printer, and every machine on the floor gets a scannable service history. Facilities teams re-run the batch quarterly as inventory changes.
- Coupon and promo codes. Marketing exports a list of unique promo URLs, one per recipient or region. Because each row is distinct, each printed piece is individually trackable by its landing URL parameters — a poor man’s attribution system with zero ad-tech involved.
- Event badges and place cards. The registration export becomes a badge batch in one pass — the event guide walks through matching filenames to badge templates with a data merge.
- Retail shelf labels. One row per SKU pointing at the product detail page. When the catalog team re-platforms the site, a dynamic batch means the shelf labels survive; a static batch means winter re-labeling.
- Documents and rooms. Law and property firms batch codes to per-matter or per-room pages — the filename column carries the room or matter number, so the person hanging codes on doors never guesses.
How much data fits in a batch code
QR capacity is not one number — codes come in versions from 21×21 modules up to 177×177, and the generator picks the smallest version that fits each row’s content at the chosen error-correction level. Practical implications for batches: a list of short links (under ~50 characters) produces small, coarse, forgiving codes that scan from across a table; a column of 200-character UTM-tagged URLs produces dense version-10-plus patterns that demand more physical size and better print quality. If your URLs are long, either shorten them at the source, drop tracking parameters you will never read, or switch the batch to dynamic codes — the printed pattern then encodes only a short redirect regardless of destination length, and every code in the run comes out uniformly small. Mixed-length columns are also worth a glance: one 400-character outlier row in an otherwise short batch will print noticeably denser than its neighbors, which looks like a defect on a wall of otherwise identical labels.
Common questions
- Does the first row have to be headers?
- Yes — headers are how you choose which column holds the data, filenames, and labels. A header row also makes the sheet self-documenting for whoever inherits it.
- What can each row encode?
- URLs or plain text, up to roughly 2,900 characters per code. WiFi and vCard payloads are single-code workflows in the Generator tab; batches are for lists.
- How are files named in the ZIP?
- By your chosen filename column, sanitized for filesystem safety, or sequentially if you did not pick one.
- Can each code have a different color?
- Not per-row — styling is batch-wide so printed sets look consistent. Run separate batches for separate styles.
- Is there a row limit on my file?
- You can upload a file of any size; the plan cap applies to how many rows generate per batch. Over-cap uploads process the first N rows and tell you exactly where they stopped.
- Do bulk-generated codes expire?
- Never. Static codes are self-contained images; once downloaded they work forever, whether or not you ever visit this site again.