Convert SketchUp .skp models to IFC 4 — without SketchUp Pro, without Trimble's SDK, and without a single dependency.
pip install skp2ifc
skp2ifc house.skp -o house.ifcfrom skp2ifc import convert_file
ifc_text, report = convert_file("house.skp")
print(report.summary())
# SketchUp 26.1.256: walked 16464 placements, wrote 260 elements
# (22 door, 190 wall, 48 window) across 2 storey(s).SketchUp's IFC export is a Pro feature. Reading .skp outside the application normally means Trimble's C SDK, which is a per-platform binary with its own licence. So if you're on SketchUp Free, or building a pipeline that never opens SketchUp at all, there hasn't been a way to get a semantic model out.
This is that way. Pure Python, standard library only, runs anywhere.
A semantic IFC model, not a mesh:
IfcProject→IfcSite→IfcBuilding→IfcBuildingStorey, correctly aggregated- Typed elements —
IfcDoor,IfcWindow,IfcWallStandardCase,IfcStair,IfcRailing,IfcRamp - Placements, in millimetres, relative to their storey
- Overall width and height on openings, where the model reveals them
- A provenance property set on every element recording how its data was derived
Geometry is not converted. SketchUp already exports COLLADA and OBJ for free if triangles are what you need. The thing nobody offers for free is the semantic layer, so that's what this does.
A .skp is not BIM. There is no IfcSpace, no door-width property, no fire rating. There is geometry organised by layer, and names somebody typed. Two signals carry nearly everything:
Layer names. Architects layer to a convention, usually the AIA one. 1-DOOR, 2-WIND, A-WALL, S-STRS — one string gives both what a thing is and which storey it's on. Firms off AIA still layer descriptively ("upper level walls", "x stairs"), which keyword matching catches.
Component names. FlexTools and similar name door components after their size. D30L is a 3'-0" left-hand door; D210R is a 2'-10" right-hand one. The feet-inches split is chosen so inches land under 12 and feet stay plausible for an opening — which is what makes D210 read as 2'-10" rather than 210 inches.
Run --inspect before converting to see what the tool recognises in your model:
skp2ifc house.skp --inspecthouse.skp
SketchUp version : 26.1.256
layers : 64
definitions : 14706
placements : 16464
recognised : 260
by kind : 22 door, 190 wall, 48 window
storeys : Level 1, Level 2
layers not recognised as building elements:
C-TOPO
I-FURN
...
If the recognised count is low, your layer names are the reason — and the list tells you which ones to look at.
Some of these are fixable and some are inherent. Know which is which before you rely on this:
| Limit | Why |
|---|---|
| No rooms | SketchUp models carry no room boundaries. No IfcSpace is written, and nothing that depends on rooms — areas, occupancy, room-based code checks — can be recovered from the model alone. This is inherent. |
| No geometry | By design. Use COLLADA/OBJ export for meshes. |
| Sizes are inferred | Dimensions come from decoding component names, not from measuring geometry. Every element carries DerivationBasis and DerivationConfidence in a property set so an inference is never mistaken for a measurement. |
| SketchUp 2021+ | Older files use an MFC archive container this reader doesn't handle. It says so rather than producing nonsense. |
| Unconventional layers | If a model doesn't layer to any recognisable convention, little is recognised. --inspect shows you that up front. |
The honest summary: this works well for doors, adequately for windows and walls, and not at all for rooms.
The .skp format is proprietary and undocumented. This reader was built on format knowledge derived from the MIT-licensed openskp — see NOTICE for full attribution.
A future SketchUp release can break this. Treat a parse failure as an expected outcome and handle it, rather than assuming a clean parse.
One trap, recorded here because it cost real time: the instance transform record is 13 doubles — a 3×3 rotation, translation at indices 9–11, scale at 12. That is not the 16-element column-major layout SketchUp's Ruby API documents, where translation sits at 12–14. Read it the documented way and every element returns x=1.0, y=z=0, silently collapsing every storey onto the ground floor.
Round-tripped against a real 128 MB architectural project: SketchUp → IFC → an independent IFC reader → the same 22 doors with identical widths, storeys and tags. Door widths survive exactly (914.4 mm ⇄ 36″).
pip install -e ".[dev]"
pytestThe highest-value contributions, roughly in order:
- More layer conventions. If your firm's naming isn't recognised, open an issue with a few layer names — that's usually a small change to
semantics.pyand it helps everyone using the same convention. - More component-name conventions for opening sizes.
- Geometry, if you want it. Deliberately absent, not accidentally.
- Pre-2021 containers (MFC archive).
MIT — see LICENSE. Built at DataVisions.ai for a building-code compliance pipeline, and split out because the conversion problem is everyone's, not ours.