Skip to content

STEP File Format

Maarten Vroegindeweij edited this page Feb 18, 2026 · 1 revision

STEP File Format

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.

File Extension

IFC STEP files use the .ifc extension. The format is plain text (UTF-8 compatible).

File Structure

A STEP file has three sections:

ISO-10303-21;
HEADER;
  /* header entities */
ENDSEC;
DATA;
  /* data entities */
ENDSEC;
END-ISO-10303-21;

1. Header Section

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')

2. Data Section

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>, ...);

Value Types

STEP supports these value types:

Integers

123
-42
0

Real Numbers

3.14
-0.5
1.0E-6
2.5E3

Strings

Single-quoted, with escaping:

'Hello World'
'It''s escaped'          /* ' inside string → '' */
'Line 1\nLine 2'        /* no escape — literal \n */

Unicode Strings

'\X\E9'                  /* ISO 8859-1: é */
'\X2\00E9\X0\'           /* UCS-2: é */
'\X4\0001F600\X0\'       /* UCS-4: 😀 */
'\S\e'                   /* ISO 8859 high-bit: é */

Booleans

.T.        /* true */
.F.        /* false */
.U.        /* unknown (LOGICAL) */

Enumeration Values

.SOLIDWALL.
.ELEMENT.
.ADDED.
.NOTDEFINED.

Entity References

#42        /* reference to entity with ID 42 */
#1000

Omitted Values (null)

$          /* attribute not provided */

Derived Values

*          /* attribute is derived (computed) */

Lists

(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 */

Typed Values

A type name wrapping a value:

IFCLABEL('My Label')
IFCREAL(3.14)
IFCBOOLEAN(.T.)
IFCINTEGER(42)
IFCIDENTIFIER('ABC-123')

Complete Example

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;

How Ifc-Factory Handles STEP

Ifc-Factory uses a two-pass approach:

Pass 1: step-serializer (schema-agnostic)

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.

Pass 2: step-parser (schema-aware)

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

Encoding Considerations

  • 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)

See Also

Clone this wiki locally