Parse Revit file format
npm install @phi-ag/rvt



Parse Revit file format
pnpm add @phi-ag/rvt
Node.js / Bun
``ts
import { basicFileInfo, thumbnail } from "@phi-ag/rvt";
import { openPath } from "@phi-ag/rvt/node";
const file = await openPath("family.rfa");
const info = await basicFileInfo(file);
const image = await thumbnail(file);
console.log(info);
`
Deno
`ts
import { basicFileInfo, thumbnail } from "@phi-ag/rvt";
import { openPath } from "@phi-ag/rvt/deno";
using file = await openPath("family.rfa");
const info = await basicFileInfo(file.data);
const image = await thumbnail(file.data);
console.log(info);
`
Browser
`ts
import { basicFileInfo, openFile, thumbnail } from "@phi-ag/rvt";
// Get a file handle from
// see https://developer.mozilla.org/en-US/docs/Web/API/File_API/Using_files_from_web_applications
const selectedFile = document.getElementById("input").files[0];
const file = await openFile(selectedFile);
const info = await basicFileInfo(file);
const image = await thumbnail(file);
console.log(info);
`
If you don't want to throw errors, use tryOpenPath, tryOpenFile, tryBasicFileInfo and tryThumbnail
`ts
tryOpenPath("valid.rvt");
// => { ok: true; data: ... }
tryOpenPath("invalid.rvt");
// => { ok: false; error: "Error message" }
tryBasicFileInfo(validFile);
// => { ok: true; data: { version, build, ... } }
tryBasicFileInfo(invalidFile);
// => { ok: false; error: "Error message" }
`
Install fnm or nvm (nvm-windows)
Install Node.js
fnm use
Install pnpm
corepack enable
corepack prepare --activate
Install packages
pnpm i
Watch
pnpm dev
Test
pnpm test
The code in this repository was created through clean-room reverse engineering.
- 7zip
- binwalk
- Hex editor (eg. ImHex)
1. Pick a file you want to inspect. I'm using racbasicsamplefamily-2026.rfa for this example.
2. Extract the Compound File Binary Format using 7z.
`
7z x racbasicsamplefamily-2026.rfa
.
├── BasicFileInfo
├── Contents
├── Formats
│ └── Latest
├── Global
│ ├── ContentDocuments
│ ├── DocumentIncrementTable
│ ├── ElemTable
│ ├── History
│ ├── Latest
│ └── PartitionTable
├── PartAtom
├── Partitions
│ └── 69
├── RevitPreview4.0
└── TransmissionData
`
3. Recursively analyze and extract data using binwalk.
`
binwalk -Me Global/ElemTable
extractions/
├── ElemTable -> /home/peter/rdp/family-2026/Global/ElemTable
└── ElemTable.extracted
└── 8
└── decompressed.bin
`
4. Use a hex editor to inspect the data.
``
imhex extractions/ElemTable.extracted/8/decompressed.bin
5. Start to guess what the data could represent.
`
Hex View 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 C9 05 C8 07 00 00 00 00 00 00 00 00 00 00 00 00 ................
`
After looking at a couple of files I'm thinking:
- The first byte could indicate the file version, seems to be consistent for a given Revit version.
- The second byte seems to be always 05.C8 07 00 00
- Interpreting the next 4 bytes as little-endian int32 is 1992.int32
- I believe this is the total amount of entries in this file.
- It seems strange that they are using for this value as they moved to int64 element ids, see 64-Bit Element Ids, Maybe?int64
- After the initial 6 bytes the file can be processed in 40 byte chunks (everything little-endian):
- Id: int32
- Unknown (1): int32
- Unknown (2): int32
- Unknown (3): int64
- Id (2): (seems to be always identical to the first id)int64
- Unknown (4): int32
- Unknown (5):
This is as far as I got for ElemTable`.