# Parquet

Parquet is a binary columnar format with a declared schema, which makes it the most compact and the most strictly typed way to submit a product feed. OpenAI prefers it, and it is the only format documented here where the field types are part of the file rather than a convention.

- **Canonical URL:** https://www.feedlab.io/knowledge/formats/parquet
- **Last reviewed:** 18 September 2026
- **Source:** feedlab knowledge base
- **Licence:** free to quote and cite with attribution to feedlab


## Specification

| Property | Value |
| --- | --- |
| Format | Apache Parquet feed |
| Content type | `application/vnd.apache.parquet` |
| Compression | Compression is internal to the format. Zstd is the preferred codec for an OpenAI feed, and there is no separate gzip step. |
| One product is | A binary file holding a schema and then the data stored column by column rather than row by row. One product is a row in the logical sense, but its values are physically grouped with the same field from every other product, which is what makes it compress so well. |
| Escaping | There is no escaping, because the format is not text: a comma, a quote or a newline inside a description is simply part of a value. What replaces escaping is type discipline, and the rule that matters is declaring identifiers as strings rather than integers so leading zeros survive. |


### File extensions

- `.parquet`



### Example

```
# Parquet is a binary columnar format, so what matters is the schema rather than the bytes.
# The same two products as the other examples on this site, as a Parquet schema:

message product {
  required binary item_id        (STRING);
  required binary title          (STRING);
  required binary description    (STRING);
  required binary url            (STRING);
  required binary image_url      (STRING);
  required binary availability   (STRING);
  required binary price          (STRING);   # "49.00 GBP" — amount and ISO code in one value
  required binary brand          (STRING);
  required binary seller_name    (STRING);
  optional binary gtin           (STRING);   # string, not integer: leading zeros are significant
  optional binary group_id       (STRING);
  optional boolean listing_has_variations;
  optional group  variant_dict (MAP) {
    repeated group key_value {
      required binary key   (STRING);
      required binary value (STRING);
    }
  }
}
```


### Which channels accept it

| Channel | Support | Notes |
| --- | --- | --- |
| OpenAI | Preferred | The preferred format, with zstd compression. |
| Google Shopping | Not supported | Google takes text or XML files. |
| Meta | Not supported | Meta takes CSV, TSV, XML or Google Sheets. |
| Microsoft Advertising | Not supported | Microsoft takes tab-delimited text or XML. |
| Pinterest | Not supported | Pinterest takes CSV, TSV or XML. |



## What breaks this format

### Typing an identifier as a number destroys it

Parquet will happily store a GTIN as an int64, and a twelve-digit UPC beginning with zero loses that zero permanently. Unlike a text format, there is no way to tell afterwards that it was ever there. Every identifier belongs in a string column.

### You cannot inspect it with an editor

A broken CSV can be opened and read. A Parquet file requires tooling, which means a validation step in your own pipeline is not optional: whatever you cannot see, you have to check programmatically before it is pushed.

### The schema has to stay stable

Because the types are declared in the file, a generator that infers them from the data can produce a different schema when the data changes, for instance typing a column as integer on the day every value happens to be numeric. Declare the schema explicitly rather than letting a library guess it per run.

### It is the right choice only at scale

Parquet earns its complexity on a large catalogue, where the compression and the typing both pay off. For a few thousand products, gzipped TSV or JSONL is easier to build, easier to debug and accepted by the same channel.








## Frequently asked questions

### Why does OpenAI prefer Parquet for a product feed?

Because it is columnar and typed: a large catalogue compresses far smaller than the equivalent text file, and the field types are declared in the file rather than inferred from the values.

### How should GTINs be typed in a Parquet feed?

As strings, always. An integer column silently discards leading zeros, and because the format is binary there is no way to notice afterwards.

### Do I need Parquet, or will gzipped TSV do?

Gzipped TSV is accepted and is much easier to produce and debug. Parquet is worth the extra work on a large catalogue, where the size and typing benefits are real.

### What compression does a Parquet feed use?

Compression is built into the format, with zstd preferred for an OpenAI feed. There is no separate gzip step, and adding one is not expected.




## Primary sources

- [OpenAI: Product feed file upload overview](https://developers.openai.com/commerce/specs/file-upload/overview)
- [Apache Parquet file format](https://parquet.apache.org/docs/file-format/)



