COPC — Cloud Optimized Point Cloud — is a way of laying out a LAZ file so that software can read part of it without downloading all of it. The points are grouped into the nodes of an octree, each node is one compressed chunk, and a small index at the end says where every chunk is. A viewer opens the header, reads the index, and fetches only the nodes that fall inside its view at the level of detail it needs.
The specification was published in 2021 by Hobu, Inc., and it is deliberately small: a COPC file is an ordinary LAZ 1.4 file with two extra records and a rule about how the points are ordered. Anything that reads LAZ reads it. Anything that understands the two records can stream it.
The problem it solves
A plain LAS or LAZ file stores points in whatever order the scanner produced them, usually by time. To draw any part of it you have to read all of it, because the points for one corner of the survey are scattered through the entire file. For a 200 MB tile on a local disk that is fine. For a 20 GB survey in cloud storage, viewed over a network, it is not — and the first web point cloud viewers dealt with it by pre-processing the data into thousands of small files in a directory tree, one per octree node.
That works, but a directory of ten thousand files is awkward to move, version, or hand to a client. COPC puts the same octree inside a single file, and relies on a feature every HTTP server already has: the Range header, which asks for one byte span of a file. The result is a single .copc.laz that opens in every LAZ tool and streams into any COPC-aware one.
How the file is organised
| Part | Where | What it is |
|---|---|---|
| LAS 1.4 header | Bytes 0–374 | An ordinary header. Point format must be 6, 7 or 8, compression bit set. |
copc info VLR | Bytes 375–588 | Must be the first VLR. 160-byte payload: octree centre and half-size, root spacing, location of the root hierarchy page, GPS time range. |
| Other VLRs | After the info record | The laszip parameters, the WKT coordinate system, anything else — as in any LAZ. |
| Point data | From the point data offset | One LAZ chunk per octree node, in any order, located by the hierarchy rather than the chunk table. |
copc hierarchy EVLR | After the points | The index: 32-byte entries giving each node's key, byte offset, byte size and point count, in pages that can themselves be loaded on demand. |
The octree
The root node is a cube — a cube, not the bounding box — centred on the octree centre and extending half-size in every direction, large enough to contain all the points. Each level divides every node into eight children. A node is named by its key: the level and its X, Y and Z position within that level, so 0-0-0-0 is the root, 1-0-1-0 one of its children, and so on to whatever depth the data needs.
Every node holds a subsample of the points inside its cube, thinned so that no two are closer than the node's spacing — the root spacing from the info record, halved at each level. Points held by a node are not repeated in its children; the children hold the points the parent left out. So the root alone is a coarse but complete picture of the whole survey, root plus level one is finer, and the union of every node is the entire file exactly once.
That is what makes level of detail free. A viewer looking at the whole survey from far away draws the root and one or two levels down. Zooming into a building, it fetches the deeper nodes under that building only, and nothing for the fields around it.
The hierarchy
The hierarchy EVLR is the index. Each 32-byte entry names a node and says where its chunk is and how many points it holds. A point count of −1 means the entry points at another page of hierarchy entries rather than at data, so a viewer can load the index for a deep octree incrementally too, instead of reading a multi-megabyte table before showing anything. A count of zero means the node is empty but may have children.
To see a real hierarchy laid out — depth, nodes and points per level, spacing per level, and whether the index agrees with the header — open a file in the COPC viewer's inspector panel. It reads the info record and the hierarchy pages and nothing else.
What the host has to do
Streaming depends on the server, and three things can go wrong, each with a different cause:
- Cross-origin requests refused. A browser will not read a file from another domain unless that domain sends an
Access-Control-Allow-Originheader. Nothing a viewer does can fix this; the host has to be configured. - Range ignored. A server that answers a range request with the whole file (status 200 instead of 206) serves COPC exactly as badly as plain LAZ. Most object stores honour ranges; some static-site hosts and CDN configurations do not.
- Content-Range hidden. Browsers may only read a short list of response headers cross-origin, and
Content-Range— which carries the total file size — is not on it. The host must add it toAccess-Control-Expose-Headers. Amazon S3 does not by default. A viewer can work around this with a HEAD request, but not every host allows those either.
A good COPC viewer reports which of the three it hit rather than saying "could not load", because the fix for each is different and none of them is in the viewer.
Making a COPC file
Converting to COPC means rewriting the file: every point is sorted into its octree node, each node is compressed as a chunk of its own, and the info and hierarchy records are written around the result. It takes roughly as long as reading and writing the data, because every point moves. The source does not need to be LAS 1.4 — older point formats are promoted to 6, 7 or 8 on the way, and any class above 31 or return above 5 that the older format could not express was never there to lose.
Conversion to COPC is not offered on this site yet. The viewer reads files that already are, and the inspector tells you whether a file is one.
Reading one
Every LAZ reader opens a COPC file as a whole, because it is valid LAZ. Streaming needs a reader that understands the two records and asks the host for byte ranges.
Open a COPC file in your browser — from disk or straight from a URL. The viewer reads the hierarchy and fetches only the nodes in view, shows the running download total so the trade-off stays visible, and names the specific hosting problem when a URL will not stream.
Checking whether a file is COPC
The extension is a convention, not a guarantee. A real COPC file has the copc info record as its very first VLR, at byte 375, in a LAZ 1.4 file with point format 6, 7 or 8. A LAZ file that was merely renamed will have a laszip or projection record there instead, and a file that carries a copc record but was later re-compressed by a tool that did not understand it has an index pointing at chunks that no longer exist. The LAS inspector decodes the info record and checks the rest of the layout against the specification, so either case is visible in a second.
For what COPC is being compared against, see LAS vs LAZ; for the underlying container, what is a LAS file.