-
Notifications
You must be signed in to change notification settings - Fork 1
STEP File Format
Maarten Vroegindeweij edited this page Feb 18, 2026
·
1 revision
IFC files use the STEP Physical File format (ISO 10303-21), also known as Part 21 or SPF. This page explains the format in detail.
IFC STEP files use the .ifc extension. The format is plain text (UTF-8 compatible).
A STEP file has three sections:
ISO-10303-21;
HEADER;
/* header entities */
ENDSEC;
DATA;
/* data entities */
ENDSEC;
END-ISO-10303-21;
The header contains three mandatory entities:
HEADER;
FILE_DESCRIPTION(
('ViewDefinition [CoordinationView]'), /* description */
'2;1' /* implementation level */
);
FILE_NAME(
'example.ifc', /* name */
'2024-01-15T10:30:00', /* timestamp */
('Architect Name'), /* author */
('Company Name'), /* organization */
'Ifc-Factory 0.1.0', /* preprocessor */
'Ifc-Factory 0.1.0', /* originating system */
'' /* authorization */
);
FILE_SCHEMA(('IFC4X3'));
ENDSEC;
| Entity | Purpose |
|---|---|
FILE_DESCRIPTION |
View definitions and implementation level |
FILE_NAME |
File metadata (name, timestamp, author, software) |
FILE_SCHEMA |
Schema identifier (e.g., 'IFC4X3') |
The data section contains all entity instances:
DATA;
#1 = IFCPROJECT('2TGt$H0E5Cexq0Fmv1x7tP', #2, 'My Project', $, $, $, $, (#10), #11);
#2 = IFCOWNERHISTORY(#3, #6, $, .ADDED., $, $, $, 1705312200);
#3 = IFCPERSONANDORGANIZATION(#4, #5, $);
/* ... more entities ... */
ENDSEC;
Each line follows the pattern:
#<id> = <TYPENAME>(<attribute1>, <attribute2>, ...);
STEP supports these value types:
123
-42
0
3.14
-0.5
1.0E-6
2.5E3
Single-quoted, with escaping:
'Hello World'
'It''s escaped' /* ' inside string → '' */
'Line 1\nLine 2' /* no escape — literal \n */
'\X\E9' /* ISO 8859-1: é */
'\X2\00E9\X0\' /* UCS-2: é */
'\X4\0001F600\X0\' /* UCS-4: 😀 */
'\S\e' /* ISO 8859 high-bit: é */
.T. /* true */
.F. /* false */
.U. /* unknown (LOGICAL) */
.SOLIDWALL.
.ELEMENT.
.ADDED.
.NOTDEFINED.
#42 /* reference to entity with ID 42 */
#1000
$ /* attribute not provided */
* /* attribute is derived (computed) */
(1, 2, 3) /* list of integers */
(#10, #20, #30) /* list of entity refs */
('a', 'b', 'c') /* list of strings */
((1.0, 2.0), (3.0, 4.0)) /* nested lists */
() /* empty list */
A type name wrapping a value:
IFCLABEL('My Label')
IFCREAL(3.14)
IFCBOOLEAN(.T.)
IFCINTEGER(42)
IFCIDENTIFIER('ABC-123')
A minimal IFC4X3 file:
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((''), '2;1');
FILE_NAME('minimal.ifc', '2024-01-15T10:00:00', (''), (''), 'Ifc-Factory', 'Ifc-Factory', '');
FILE_SCHEMA(('IFC4X3'));
ENDSEC;
DATA;
#1 = IFCPROJECT('0YvctVUKr0kugbFTf53O9L', #2, 'Minimal Project', $, $, $, $, (#10), #11);
#2 = IFCOWNERHISTORY(#3, #6, $, .ADDED., $, $, $, 1705312200);
#3 = IFCPERSONANDORGANIZATION(#4, #5, $);
#4 = IFCPERSON($, 'Doe', 'John', $, $, $, $, $);
#5 = IFCORGANIZATION($, 'Example Corp', $, $, $);
#6 = IFCAPPLICATION(#5, '0.1.0', 'Ifc-Factory', 'IfcFactory');
#10 = IFCUNITASSIGNMENT((#20, #21, #22));
#11 = IFCGEOMETRICREPRESENTATIONCONTEXT($, 'Model', 3, 1.0E-5, #12, $);
#12 = IFCAXIS2PLACEMENT3D(#13, $, $);
#13 = IFCCARTESIANPOINT((0.0, 0.0, 0.0));
#20 = IFCSIUNIT(*, .LENGTHUNIT., $, .METRE.);
#21 = IFCSIUNIT(*, .AREAUNIT., $, .SQUARE_METRE.);
#22 = IFCSIUNIT(*, .VOLUMEUNIT., $, .CUBIC_METRE.);
#100 = IFCSITE('3Do0GNiST7hxjbCRxRPMzj', #2, 'Site', $, $, $, $, $, .ELEMENT., $, $, $, $, $);
#101 = IFCBUILDING('1DkNMJJe97QvNgY8gSWmrZ', #2, 'Building', $, $, $, $, $, .ELEMENT., $, $, $);
#102 = IFCBUILDINGSTOREY('2XQ1jj47jCGPOIF$KQPz5B', #2, 'Ground Floor', $, $, $, $, $, .ELEMENT., 0.0);
#200 = IFCRELAGGREGATES('3CUHW5iK19wOy$S6YctEIy', #2, $, $, #1, (#100));
#201 = IFCRELAGGREGATES('0iF1jm0qv1NOefJcyTkbXR', #2, $, $, #100, (#101));
#202 = IFCRELAGGREGATES('1vnThPVir8pBUYGfMM$KF1', #2, $, $, #101, (#102));
ENDSEC;
END-ISO-10303-21;
Ifc-Factory uses a two-pass approach:
import { readStepFile } from '@ifc-factory/step-serializer';
const stepFile = readStepFile(source);
// stepFile.entities = Map<number, { id, typeName, attributes: StepValue[] }>This pass extracts raw entity records without knowing what IFCWALL means.
import { parseStepToEntities } from '@ifc-factory/step-parser';
const result = parseStepToEntities(source);
// result.entities = Map<number, { expressID, type: 'IfcWall', GlobalId, Name, ... }>This pass uses SCHEMA_METADATA to map positional attributes to named properties:
IFCWALL('guid', #2, 'name', ...)
↓ ↓ ↓
GlobalId Owner Name
- STEP files are typically ASCII or UTF-8
- Non-ASCII characters use
\X\,\X2\,\X4\escape sequences - Line length has no formal limit, but some implementations wrap at 80 characters
- Entity IDs (
#N) are not required to be sequential - Comments use
/* ... */syntax (rarely used in practice)
- step-serializer — the package that handles raw STEP I/O
- step-parser — the package that adds IFC schema awareness
- Architecture — overall parsing architecture
- IFC Concepts — IFC data model overview
Ifc-Factory
Getting Started
Concepts
Packages
API & Reference
Development