| name | ifc-syntax-step-physical-file |
| description | Use when reading, writing, or debugging the .ifc STEP Physical File: the ISO-10303-21 skeleton, the HEADER section (FILE_DESCRIPTION, FILE_NAME, FILE_SCHEMA), the DATA section instance syntax, the special tokens, value notation, string escaping, or the ifcZIP container. Prevents emitting attributes out of declared order, serializing inverse or derived attributes, confusing the unset token with the derived token, writing raw non-ASCII bytes into a string, and putting more than one model file in an ifcZIP. Covers the file skeleton, the three header entities and the ViewDefinition convention, hash-id instance syntax, forward and backward references, dollar and asterisk tokens, enum and boolean dot notation, typed-value wrapping, aggregates, the control directives, and PKZip 2.04g ifcZIP packaging. Keywords: STEP physical file, SPF, .ifc, ISO 10303-21, Part 21, ISO-10303-21, HEADER, DATA, ENDSEC, FILE_DESCRIPTION, FILE_NAME, FILE_SCHEMA, ViewDefinition, positional attributes, dollar sign, asterisk, forward reference, escape directive, X2, ifcZIP, how do I read an IFC file, IFC file wont parse, garbled characters in IFC, what is the dollar sign in IFC, attribute count mismatch, IFC header section.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires IFC IFC2x3,IFC4,IFC4.3. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
IFC STEP Physical File Syntax
The .ifc file is a STEP Physical File (SPF, also called Part 21 or p21),
governed by ISO 10303-21. It is a clear-text encoding in which each entity
instance is a line and attribute values are an ordered sequence of unnamed
values. This skill covers the file skeleton, the HEADER section, the DATA
section instance syntax, value notation, string escaping, and the ifcZIP
container.
Verified against the buildingSMART IFC formats documentation, the IFC
Header Data Implementation Guide v1.0.2, the ifcZIP implementation
agreement CV-2x3-154, and ISO 10303-21. Applies to IFC2x3, IFC4, IFC4.3:
the SPF syntax is identical across all three; only the FILE_SCHEMA
identifier and the entity set differ.
Quick Reference
The file skeleton
A .ifc file ALWAYS has exactly this frame:
ISO-10303-21;
HEADER;
...three header entities...
ENDSEC;
DATA;
...entity instances...
ENDSEC;
END-ISO-10303-21;
The file ALWAYS begins with ISO-10303-21; and ends with
END-ISO-10303-21;. Each section ALWAYS closes with ENDSEC;. IFC files
use only the HEADER and DATA sections. NEVER emit the optional Part 21
ANCHOR or REFERENCE sections: IFC tooling does not expect them.
The three header entities
The HEADER section ALWAYS contains exactly three entities, in this fixed
order: FILE_DESCRIPTION, FILE_NAME, FILE_SCHEMA.
| Entity | Carries |
|---|
FILE_DESCRIPTION | A description list (used for the ViewDefinition) and implementation_level |
FILE_NAME | Name, timestamp, author, organization, preprocessor, originating system, authorization |
FILE_SCHEMA | The schema identifier list: IFC2X3, IFC4, or IFC4X3 |
A reader ALWAYS dispatches its parser by the FILE_SCHEMA value. Full
signatures are in references/methods.md.
The data instance syntax
Each DATA-section line is one entity instance:
#<id>=ENTITYNAME(attr1,attr2,...);
| Element | Rule |
|---|
#<id> | # plus a positive integer. Unique within the file. Numbering need not be contiguous and carries NO meaning. |
ENTITYNAME | The entity keyword in UPPER CASE (IFCWALL, IFCPROJECT). |
(...) | Attributes in EXPRESS declared order, including all inherited explicit attributes. |
; | Every instance line ends with a semicolon. |
ALWAYS serialize explicit attributes only. NEVER serialize INVERSE or
DERIVED attributes: they are omitted from the positional sequence.
The special tokens
| Token | Meaning |
|---|
$ | An unset OPTIONAL attribute. The slot exists; there is no value. |
* | A slot whose value is derived in this entity but was explicit in a supertype. The slot is held by *; the value is computed, not stored. |
#id | A reference to another instance. May point forward (later in the file) or backward. |
Value notation cheat sheet
| Value kind | Written as | Example |
|---|
| String | Single-quoted | 'Wall-001' |
| Embedded apostrophe | Doubled | 'don''t' |
| Real / integer | Plain; reals carry a dot | 3.14, 0., 255 |
| Enumeration | Dot-delimited, upper case | .SOLIDWALL. |
| Boolean | .T. or .F. | .T. |
| Logical | .T., .F., or .U. | .U. |
| Typed (select / measure) value | Type keyword wrapping the value | IFCBOOLEAN(.T.), IFCINTEGER(255) |
| Aggregate (LIST, SET, BAG, ARRAY) | Comma-separated in parentheses | (#84,#85,#86), (0.,0.,0.) |
| Reference | #id token | #5 |
| Unset optional | $ | $ |
Decision Trees
Which token does this attribute slot get?
The attribute in this positional slot is...
|
+- An explicit attribute with a value
| -> write the value (string, number, enum, #id, aggregate, ...).
|
+- An explicit OPTIONAL attribute with no value
| -> write $ . The slot stays; no value is given.
|
+- Explicit in a supertype but re-declared DERIVE in this entity
| -> write * . The slot is held; the value is computed.
|
+- Declared DERIVE or INVERSE in this entity itself
-> the slot does NOT exist. Omit it entirely. NEVER write $ or *.
NEVER confuse $ with *. $ means "optional, not set". * means
"this slot's value is derived". Using $ for a derived re-declared slot,
or * for a plain unset optional, produces an attribute the importer
reads with the wrong semantics.
Is this attribute serialized at all?
What kind of attribute is it (from the EXPRESS schema)?
|
+- Explicit (declared directly or inherited as explicit)
| -> YES, it occupies a positional slot. Always present.
|
+- Re-declared from explicit to DERIVE in this entity
| -> YES, the slot is present, held by * .
|
+- DERIVE declared in this entity
| -> NO. Omitted. The value is computed by the reader.
|
+- INVERSE
-> NO. Omitted. The reader rebuilds it by scanning references.
The positional attribute count of an instance ALWAYS equals the number of
explicit attributes (direct plus inherited) of that entity. A mismatch is
the most common parse failure. See references/anti-patterns.md.
Raw character or escape directive?
The string contains a character that is...
|
+- Printable ASCII (U+0020 to U+007E), except the apostrophe
| -> write it directly.
|
+- An apostrophe
| -> double it: ' becomes '' .
|
+- A backslash
| -> double it: \ becomes \\ .
|
+- Non-ASCII (accented letter, symbol, CJK, emoji)
-> encode with a control directive: \X\, \X2\..\X0\, or \X4\..\X0\.
NEVER write the raw byte. See the escaping pattern below.
Patterns
Verified snippets. Full notation detail is in references/methods.md;
complete files are in references/examples.md.
Pattern: write the HEADER section
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME(
'project.ifc',
'2026-05-20T11:35:07',
('A. Author'),
('Example Organization'),
'IfcOpenShell 0.8',
'ExampleApp 1.0',
'A. Author');
FILE_SCHEMA(('IFC4'));
ENDSEC;
FILE_DESCRIPTION carries the Model View Definition in its description
list. The agreed convention is a ViewDefinition [Name] keyword string.
implementation_level is ALWAYS '2;1' for IFC files. FILE_NAME fields
that are unknown ALWAYS take '' or $, NEVER an invented value. Each
header string is limited to 256 characters.
Pattern: write a DATA instance in declared order
The positional order is the EXPRESS declared order, inherited attributes
first. For IfcWall (IFC4, IFC4.3) the 9 explicit attributes are:
#21=IFCWALL(
'3t3TDZl_D9NOIWB0BSjzJI', /* 1 GlobalId IfcRoot */
#5, /* 2 OwnerHistory IfcRoot */
'Wall-001', /* 3 Name IfcRoot */
$, /* 4 Description IfcRoot */
$, /* 5 ObjectType IfcObject */
#18, /* 6 ObjectPlacement IfcProduct */
#19, /* 7 Representation IfcProduct */
'A-101', /* 8 Tag IfcElement */
.SOLIDWALL. /* 9 PredefinedType IfcWall */
);
In a real file the instance is written on one line. ALWAYS emit every
explicit slot. See ifc-syntax-building-elements for per-entity layouts.
Pattern: forward and backward references
A #id reference may point to an instance defined later in the file:
#21=IFCWALL('3t3TDZl_D9NOIWB0BSjzJI',#5,'Wall-001',$,$,#18,#19,'A-101',.SOLIDWALL.);
#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,$,$,$,1700000000);
Here #21 references #5 before #5 is defined. This is legal. A
conformant reader ALWAYS does a two-pass parse: index every #id first,
then resolve references. NEVER assume an instance is defined before its
first use.
Pattern: aggregates and typed values
An aggregate is comma-separated values in parentheses. IfcCartesianPoint
has exactly ONE explicit attribute, a coordinate list, so the instance
holds a list nested inside the attribute parentheses:
#100=IFCCARTESIANPOINT((0.,0.,0.));
A typed value wraps the value in its type keyword. Used for SELECT and
measure types where the reader must know the concrete type:
#46=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);
NEVER write a bare .T. where a typed value is required: the select type
needs IFCBOOLEAN(.T.) so the reader resolves the right member.
Pattern: escape non-ASCII characters
IFC follows the ISO 10303-21:2002 string model: non-ASCII characters use
control directives, NOT raw bytes.
/* the section sign U+00A7 */ 'see \X\A7 4.1'
/* the Greek letter pi U+03C0 */ '\X2\03C0\X0\'
/* an emoji U+1F600 */ '\X4\0001F600\X0\'
\X\ takes two hex digits (U+0000 to U+00FF). \X2\ takes groups of four
hex digits and is closed by \X0\. \X4\ takes groups of eight hex
digits and is closed by \X0\. ALWAYS encode non-ASCII this way for
interoperability across IFC2x3, IFC4, and IFC4.3. NEVER write a raw UTF-8
octet into an SPF string: the IFC4.3 documentation references ISO
10303-21:2002, whose string model is the control-directive model.
Pattern: package an ifcZIP
ifcZIP is a plain ZIP archive holding exactly one model file:
- The archive ALWAYS uses PKZip 2.04g (DEFLATE) compression. NO encryption,
NO deflate64, NO ZIP unicode extensions.
- The archive ALWAYS contains exactly ONE
.ifc file OR exactly ONE
ifcXML file in its main directory. NEVER more than one model file.
- The extension is
.ifcZIP; the MIME type is application/zip.
NEVER place two .ifc files in one ifcZIP: a conformant reader expects
exactly one and the result is ambiguous.
Anti-Patterns
Full detail with the failure mechanism is in references/anti-patterns.md.
The five that matter most:
- Wrong attribute count: omitting an explicit slot or adding an extra one.
The whole instance fails to parse.
- Serializing an INVERSE or DERIVED attribute as a positional value.
Shifts every following attribute by one slot.
- Using
$ for a derived re-declared slot, or * for a plain optional.
The reader applies the wrong semantics.
- Writing a raw non-ASCII byte into a string instead of a control
directive. Produces garbled text or a decode failure.
- Putting more than one model file in an ifcZIP. The reader cannot decide
which file is the model.
Reference Links
This skill
references/methods.md: the file skeleton, the three header entity
signatures, the special tokens, the value-notation table, the control
directives, and the ifcZIP rules.
references/examples.md: complete minimal valid .ifc files and
verified syntax fragments.
references/anti-patterns.md: parse-failure modes and their causes.
Related skills
ifc-syntax-express: the EXPRESS schema language whose declared order
this file's positional attributes follow.
ifc-syntax-ifcxml: the XML encoding governed by ISO 10303-28.
ifc-syntax-data-types: the IFC measure and defined types written as
typed values here.
ifc-errors-encoding-issues: diagnosing and repairing broken string
escaping and character-encoding faults.
Official sources