Summary (direct answer)
The PLY file format (Polygon File Format, also called the Stanford Triangle Format) is a single-object 3D data format that stores geometry as a set of elements (such as vertices and faces) with typed properties (such as coordinates, normals, or color) declared by an ASCII header that defines the schema for the data that follows. [1] PLY has two sub-formats — ASCII and binary — and commonly uses a format ... 1.0 header line with ascii, binary_little_endian, or binary_big_endian. [1][4]

Historical Background
The canonical “PLY Polygon File Format” specification is attributed to Greg Turk and bears a copyright (c) 1994. [1] In the specification, the format is presented as a straightforward, header-described container for polygonal data (and other element/property records) rather than as a full scene interchange language. [1]
Contemporary summaries position PLY as a format that originated in academic graphics workflows and is widely recognized in digital preservation contexts as well. [2] A Georgia Tech archival page on large 3D models notes that early versions of the format were used at Stanford University and the University of North Carolina at Chapel Hill, and describes the file as a header followed by lists including vertices and polygons. [3]
What the PLY Format Represents (Conceptual Model)
PLY represents exactly one object as a collection of elements, where each element has a fixed number of records and each record is a set of declared properties with specified scalar or list types. [1] In practice, a “mesh PLY” commonly means a file with vertex and face elements, while a “point cloud PLY” is typically a file that defines only a vertex element (and possibly additional per-vertex properties), but these are usage patterns rather than separate format revisions. [1] The original specification explicitly frames PLY as not being a general scene description language and excludes constructs such as transformation matrices and hierarchies, which constrains its role to object-level interchange rather than scene graphs. [1]
File Layout Overview (Header → Element Lists)
A PLY file consists of an ASCII header followed by element data written as one contiguous list per element, in the same order that the element declarations appear in the header. [1] The header declares each element’s name and number of records, and then declares each property for that element, ending with end_header. [1]
Both institutional and academic descriptions emphasize this two-part layout (header, then data lists). [2][3] The Georgia Tech overview further characterizes the common case as “a header followed by a vertex list and a polygon list,” which aligns with the typical vertex then face ordering used for meshes. [3]
Header Grammar and Required Tokens
The original specification defines a strict header preamble and keyword-based grammar: the start string ply<cr> must be the first four characters of the file and serves as a magic number, and header lines are ASCII strings terminated by carriage return. [1] The header declares the data encoding and version via a format <data format> <PLY version> line (with version commonly written as 1.0), declares each element using element <name> <number-in-file>, declares element properties using one or more property ... lines, allows keyword-identified comment lines beginning with comment, and terminates the header with end_header, after which the data section begins and is interpreted according to the declared schema. [1][4] A minimal, schematic header example (line breaks shown as ⏎ for readability) is: ply⏎ format ascii 1.0⏎ element vertex <N>⏎ property float x⏎ property float y⏎ property float z⏎ end_header⏎, where <N> is the vertex record count declared in the header. [1]
Header keywords and their roles
ply: Identifies the file as PLY, andply<cr>must begin the file as a magic number. [1]format: Declares the body encoding and PLY version usingformat <data format> <PLY version>. [1][4]element: Declares an element name and the number of records of that element in the data section. [1]property: Declares a typed property belonging to the most recently declared element, defining the per-record fields. [1]comment: Introduces a comment line in the header, identified by the leading keywordcomment. [1]end_header: Marks the end of the header and the start of the data section. [1]
Encoding Variants (ASCII vs Binary; Endianness)
The PLY specification defines two sub-formats: an ASCII representation and a binary representation. [1] In both cases, the header is ASCII and begins with the ASCII string ply followed by a carriage return as a file identifier, while the data section’s interpretation is controlled by the format line. [2]
Implementation documentation commonly recognizes three format tokens for version 1.0: ascii, binary_little_endian, and binary_big_endian. [4] The binary variants use the indicated byte order (endianness) when encoding multi-byte scalar values in the body, whereas ASCII encodes numeric values as readable text; the binary forms are therefore typically used when faster I/O and smaller files are preferred, while ASCII is often used when human inspection and ad hoc editing are prioritized. [1][4]
Scalar Data Types (Portability Constraints)
The original specification defines a fixed set of scalar property types with fixed byte sizes: char (1), uchar (1), short (2), ushort (2), int (4), uint (4), float (4), and double (8). [1] It also states a portability constraint: these sizes must not vary across implementations if files are to remain portable, which means readers and writers must treat the PLY type names as specification-level types rather than as language-native types whose sizes may differ by platform or compiler. [1]
| PLY scalar type name | Bytes | Portability notes |
|---|---|---|
char, uchar |
1. [1] | Fixed-size in the specification; implementations should not substitute platform-dependent types. [1] |
short, ushort |
2. [1] | Multi-byte scalars must follow the declared endianness in binary encodings. [1][4] |
int, uint, float |
4. [1] | Sizes are normative for portability; mismatches break binary interchange. [1] |
double |
8. [1] | Writers should emit exactly the specified width, not a “native” floating type of different size. [1] |

List Properties (Faces and Other Variable-Length Records)
Beyond fixed-width scalar properties, PLY supports variable-length data within an element record via list properties. [1] The list property syntax is declared in the header as property list <numerical-type> <numerical-type> <property-name>, where the first numerical type specifies the scalar type used to store the list length (the count), and the second numerical type specifies the scalar type of each list entry. [1] In the data section, each list instance is encoded as a count value followed by that many scalar entries, interpreted according to the two declared types. [1]
This mechanism is commonly used to represent polygonal faces as index lists into the vertex array. [1] The specification’s illustrative face encoding property list uchar int vertex_indices denotes an unsigned-char count followed by that many integer indices, with each index referencing a vertex record. [1] A Georgia Tech description of the format corroborates the same conceptual rule in simpler terms: in the polygon list, each face begins with a count, followed by that many indices. [3] Because the count is stored per face record, the same face element can naturally contain triangles, quads, and higher-order polygons in a single file without changing the element schema. [1]
Common Elements and Properties (De facto Conventions)
The specification illustrates (but does not mandate) common element names such as vertex, face, and edge, and illustrates the association of properties with these elements. [1] Likewise, commonly encountered property names such as x, y, and z for coordinates, and red, green, and blue for per-vertex color, should be treated as de facto conventions derived from examples and widespread practice rather than as enforceable requirements of the grammar. [1] Implementation-oriented documentation similarly presents typical mesh-oriented usage with vertex and face records, including a face list property such as vertex_indices, as an example of how the header-defined schema is used in practice. [4]
Non-goals and Known Limitations
In the original specification, PLY is explicitly described as not being intended to be a general scene description language, and the document enumerates omitted modeling and scene constructs, including transformation matrices, instancing, and hierarchical relationships. [1] This design positions PLY as an interchange mechanism for a single object’s geometry and associated per-element attributes rather than for a structured scene graph with reusable sub-objects. [1]
A preservation-focused description similarly frames PLY as centered on polygonal models (and closely related element/property records) rather than on full appearance and scene semantics. [2] In practical interoperability terms, the absence of standardized scene-level constructs means that workflows requiring multiple objects, object transforms, or richer material/texture behavior typically layer PLY inside an external container or adopt a different format whose specification includes such constructs. [1][2]
Interoperability Pitfalls (What Breaks in Real Pipelines)
PLY’s “schema in the header” approach enables extensibility because element and property declarations can be defined by the writer, but it also shifts interoperability risk to naming, typing, and strict parsing. [1] Readers that assume conventional property names (for example, expecting x y z or vertex_indices) may fail to import semantically equivalent files that use different names, even though the grammar allows arbitrary element/property identifiers. [1] At the byte level, strict adherence to the specification’s fixed scalar sizes is necessary for binary portability, and a mismatch between declared and actual sizes (or a mismatch between binary_little_endian/binary_big_endian and the emitted byte order) can produce silent misreads rather than hard failures. [1][4] Another recurring issue is newline handling in the header: the specification defines carriage-return-terminated ASCII header lines and requires ply<cr> at the file start, so implementations that normalize line endings without care can diverge from strict readers, even when the file is otherwise well-formed. [1]
Comparison Table (Mandatory)
PLY is commonly compared with polygon-mesh interchange formats such as OBJ and STL and with point-cloud-centric formats such as PCD, primarily along axes of schema extensibility, encoding variants, and whether the format is scoped as an object file or a broader scene container. [1][2]
| Format | Typical content focus | Extensible per-vertex / per-point fields | Encoding and scope notes |
|---|---|---|---|
| PLY | Single object described as elements with properties (often vertices and faces). [1] | Yes; arbitrary elements and properties can be declared in the header. [1] | ASCII or binary; binary supports little/big endian, and PLY is not a general scene description language. [1][4] |
| OBJ | Text-based geometry exchange commonly used for polygon meshes. [5] | Limited; attributes are represented via predefined record types rather than arbitrary typed properties. [5] | Primarily ASCII; may reference separate MTL material files, and can represent multiple named objects/groups in one file. [5] |
| STL | Triangulated surface geometry for fabrication-oriented workflows. [6] | No standardized arbitrary per-vertex property schema. [6] | Defined in ASCII and binary variants; commonly treated as a single-part surface mesh without scene structure. [6] |
| PCD | Point cloud storage with named fields described in a header. [7] | Yes; point fields are declared in the header (field names and types). [7] | Supports ASCII and binary storage modes as described by the PCL documentation; centered on point clouds rather than polygon faces. [7] |
Across these formats, PLY and PCD are similar in that both use a header to declare how subsequent records should be interpreted, which supports adding fields without revising the core grammar. [1][7] OBJ and STL instead emphasize widely understood, relatively fixed record structures, which can simplify interchange when only conventional mesh data are needed but can be constraining when pipelines require typed per-vertex metadata such as arbitrary sensor attributes or custom labels. [5][6]
Practical Parsing Checklist (Implementation-Agnostic)
Robust PLY parsing treats the header as a schema definition and then streams the body according to the declared format, element counts, and property types, including list-property count-and-payload semantics. [1] The original specification’s fixed set of scalar types (with fixed byte sizes) provides the normative basis for decoding both ASCII and binary bodies, while required keywords (ply, format, element, property, and end_header) define the minimum structure a reader should validate before interpreting data records. [1][2]
Parsing checklist
- Validate that the file begins with the magic number
ply<cr>as the first four characters. [1] - Read header lines as ASCII keyworded records up to and including
end_header, treating comments only as lines beginning withcomment. [1] - Parse the
format <data format> <PLY version>line and select the corresponding decoder (ascii,binary_little_endian, orbinary_big_endian) for the body. [1][4] - For each
element <name> <number-in-file>, store the element name, declared record count, and the ordered list of itspropertydeclarations. [1] - For each scalar
property <type> <name>, map the PLY type to its fixed byte size and numeric interpretation as defined by the specification, rejecting unknown scalar types. [1] - For each list
property list <count-type> <item-type> <name>, decode each record as a count followed by that many items, using the declared scalar types for both. [1] - Stream the body element-by-element, record-by-record, in the same order elements are declared in the header, ensuring that the number of records read matches each element’s declared count. [1]
- Treat missing
end_header, inconsistent record counts, or type-size mismatches as hard errors because they make the body ambiguous or non-portable. [1]

FAQ
What is a PLY file format and what does it store?
PLY is a single-object 3D format that stores an object as elements with typed properties defined by an ASCII header, and it has two sub-formats (ASCII and binary). (FP — two sub-formats; FP — elements/properties; FP — single object.) [1]
How does the PLY header define the schema for the data section?
The header declares each element’s record count using element <name> <number-in-file>, declares per-element fields using property ... lines, and ends the schema with end_header, after which the data must follow the declared element/property order. (FP — header structure; FP — LoC header description.) [1][2]
What is the difference between ASCII PLY and binary PLY (little endian vs big endian)?
Both ASCII and binary PLY begin with an ASCII header, but the body is encoded either as ASCII numbers (ascii) or as binary scalars in a specified byte order (binary_little_endian or binary_big_endian) for multi-byte values. (FP — LoC ASCII header statement; FP — MathWorks encoding tokens.) [2][4]
How are polygon faces represented in PLY, and why do faces start with a count?
Faces are typically stored as a list property declared with property list <count-type> <item-type> <name>, and each face record encodes a count followed by that many vertex indices into the vertex list; the count enables variable-arity polygons. (FP — list syntax; FP — uchar count + int indices meaning; FP — Georgia Tech “face begins with a count”.) [1][3]
Which scalar data types are allowed in PLY, and what are their fixed byte sizes?
The specification allows char/uchar (1 byte), short/ushort (2), int/uint (4), float (4), and double (8), and it states that these sizes must not vary across implementations for portability. (FP — scalar types and byte sizes; FP — portability statement.) [1]
Is PLY a scene format (can it store transforms, instancing, and multiple objects)?
PLY is designed to store exactly one object and is not intended to be a general scene description language; the original specification excludes transformation matrices, instancing, and hierarchical scene constructs. (FP — single object; FP — non-scene exclusions.) [1]
Sources
- The PLY Polygon File Format (Greg Turk)
- Library of Congress: PLY (Polygon File Format) (FDD 000501)
- Georgia Tech Large Models Archive: PLY – Polygon File Format
- MathWorks Documentation: The PLY Format
- Library of Congress: OBJ (Wavefront) (Format Description Document)
- Library of Congress: STL (STereoLithography) (Format Description Document)
- Point Cloud Library (PCL) Documentation: The PCD (Point Cloud Data) file format
