DXF: AutoCAD's Drawing Exchange Format
What Is DXF?
DXF — Drawing Exchange Format — is an open CAD data file format developed by Autodesk in 1982 to enable data interoperability between AutoCAD and other programs. Unlike DWG (AutoCAD's native binary format), DXF was designed from the start to be human-readable ASCII text — making it the universal neutral format for 2D and 3D CAD data exchange.
DXF files use the .dxf extension. Nearly every CAD, CAM, laser cutting, vinyl cutting, CNC machining, and architectural software application can read and write DXF. It is the most widely supported CAD interchange format in the world — more accessible than STEP or IGES for 2D work and for communication with fabrication equipment.
A binary DXF variant also exists (created with DXFOUT in binary mode) but the ASCII form is overwhelmingly standard.
DXF File Structure
Every DXF file is organized into sections, each bounded by 0\nSECTION and 0\nENDSEC marker pairs:
0 ← group code: 0 = entity/section name
SECTION
2 ← group code: 2 = name
HEADER ← section name
[header variables: $ACADVER, $INSUNITS, $EXTMIN, $EXTMAX, etc.]
0
ENDSEC
0
SECTION
2
CLASSES ← custom object class definitions (DXF R2000+)
0
ENDSEC
0
SECTION
2
TABLES ← named symbol tables: LAYER, LTYPE, STYLE, VPORT, etc.
0
ENDSEC
0
SECTION
2
BLOCKS ← block definitions (reusable symbol libraries)
0
ENDSEC
0
SECTION
2
ENTITIES ← the actual drawing entities (lines, arcs, text, etc.)
0
ENDSEC
0
SECTION
2
OBJECTS ← non-graphical objects (dictionaries, groups, XData)
0
ENDSEC
0
EOF
Group Codes
The entire DXF format is built on group code / value pairs — every line in DXF is either a group code (integer) or the value for the previous code. Group codes define the meaning of the next line:
| Group code range | Meaning |
|---|---|
| 0 | Entity type or section name |
| 1 | Primary text value |
| 2 | Name (block, section, table) |
| 5 | Entity handle (unique hex ID) |
| 6 | Linetype name |
| 7 | Text style name |
| 8 | Layer name |
| 10–19 | X coordinate (10=primary, 11=secondary…) |
| 20–29 | Y coordinate |
| 30–39 | Z coordinate |
| 40–49 | Floating-point values (radius, height, scale…) |
| 62 | Color number (ACI: 1=red, 2=yellow, 7=white/black) |
| 70–79 | Integer flags and counts |
| 100 | Subclass marker |
| 210, 220, 230 | Extrusion direction (normal vector X, Y, Z) |
Common DXF Entity Types
The ENTITIES section contains the drawing geometry:
| Entity | Code | Description |
|---|---|---|
| LINE | LINE |
Straight line from point to point |
| CIRCLE | CIRCLE |
Circle defined by center + radius |
| ARC | ARC |
Arc: center + radius + start/end angles |
| ELLIPSE | ELLIPSE |
Full ellipse or arc (DXF R2000+) |
| LWPOLYLINE | LWPOLYLINE |
Lightweight 2D polyline (most common for 2D outlines) |
| POLYLINE | POLYLINE |
Legacy 3D polyline / mesh |
| SPLINE | SPLINE |
NURBS spline curve |
| TEXT | TEXT |
Single-line text |
| MTEXT | MTEXT |
Multi-line formatted text |
| INSERT | INSERT |
Block reference (insert a named block) |
| DIMENSION | DIMENSION |
Dimension annotation |
| HATCH | HATCH |
Filled region / crosshatch pattern |
| SOLID | SOLID |
Filled triangle or quadrilateral |
| 3DFACE | 3DFACE |
Triangular or quad 3D surface face |
| MESH | MESH |
Subdivision surface mesh (DXF R2010+) |
| POINT | POINT |
Single point |
| XLINE | XLINE |
Infinite construction line |
| IMAGE | IMAGE |
Raster image reference |
| ATTRIB | ATTRIB |
Attribute value within a block insert |
DXF in Practice: Reading with ezdxf (Python)
ezdxf is the standard Python library for reading and writing DXF:
import ezdxf
from ezdxf import colors
from ezdxf.math import Vec3
# Open an existing DXF file
doc = ezdxf.readfile("floor_plan.dxf")
msp = doc.modelspace() # the main drawing space
# Iterate all entities
for entity in msp:
print(entity.dxftype(), entity.dxf.layer)
# Filter by entity type
lines = msp.query("LINE")
for line in lines:
print(f"Line: {line.dxf.start} → {line.dxf.end}")
circles = msp.query("CIRCLE")
for circle in circles:
print(f"Circle center: {circle.dxf.center}, r={circle.dxf.radius:.3f}")
lwpoly = msp.query("LWPOLYLINE")
for poly in lwpoly:
print(f"Polyline layer: {poly.dxf.layer}, vertices: {len(poly)}")
for x, y in poly.get_points():
print(f" ({x:.3f}, {y:.3f})")
# Access layer information
layers = doc.layers
for layer in layers:
print(f"Layer: {layer.dxf.name}, color: {layer.dxf.color}, on: {layer.is_on()}")
Creating a DXF File
import ezdxf
# Create a new DXF document (R2010 format)
doc = ezdxf.new("R2010")
msp = doc.modelspace()
# Set up layers
doc.layers.add("WALLS", color=colors.WHITE)
doc.layers.add("DOORS", color=colors.CYAN)
doc.layers.add("WINDOWS",color=colors.GREEN)
doc.layers.add("TEXT", color=colors.YELLOW)
# Draw floor plan
# Outer walls
msp.add_lwpolyline(
[(0,0), (10000,0), (10000,8000), (0,8000), (0,0)],
dxfattribs={"layer": "WALLS", "closed": True}
)
# Interior wall
msp.add_line((5000,0), (5000,5000), dxfattribs={"layer": "WALLS"})
# Door arc
msp.add_arc(
center=(1000, 0),
radius=900,
start_angle=0,
end_angle=90,
dxfattribs={"layer": "DOORS"}
)
# Window (gap)
msp.add_line((3000, 8000), (5000, 8000), dxfattribs={"layer": "WINDOWS"})
# Dimension
msp.add_linear_dim(
base=(0, -500),
p1=(0, 0),
p2=(10000, 0),
dxfattribs={"layer": "TEXT"}
).render()
# Text annotation
msp.add_text(
"Living Room",
dxfattribs={"height": 300, "layer": "TEXT", "insert": (2000, 4000)}
)
# Save
doc.saveas("floor_plan_output.dxf")
DXF Versions (AC Codes)
DXF files carry an $ACADVER variable in the HEADER section:
| DXF version | AutoCAD release | AC code |
|---|---|---|
| DXF R12 | AutoCAD R12 | AC1009 |
| DXF R2000 | AutoCAD 2000 | AC1015 |
| DXF R2004 | AutoCAD 2004 | AC1018 |
| DXF R2007 | AutoCAD 2007 | AC1021 |
| DXF R2010 | AutoCAD 2010 | AC1024 |
| DXF R2013 | AutoCAD 2013 | AC1027 |
| DXF R2018 | AutoCAD 2018 | AC1032 |
R12 is the most widely compatible version — supported by virtually every CAD/CAM/laser application. Export in R12 when sending files to fabrication machines or older software. Export in R2010+ when rich features (NURBS, meshes, hatches) are needed.
DXF for CNC and Laser Cutting
DXF is the dominant format for sending 2D profiles to:
- Laser cutters (Universal Laser, Trotec, Epilog, xTool, Glowforge)
- Vinyl cutters / plotters (Cricut, Silhouette, Roland)
- CNC routers (requires DXF → G-code conversion via CAM software)
- Plasma cutters
- Waterjet cutters
For cutting profiles, use LWPOLYLINE entities with closed paths on a single layer. Machines typically expect:
- All paths as closed polylines
- Units matching the machine's expectation (mm vs inches — check
$INSUNITS) - No text, dimensions, or construction lines in the cut layer
- Scale 1:1 (no scaling factors in blocks)
# Clean DXF for laser cutting: extract closed outlines only
import ezdxf
doc = ezdxf.readfile("design.dxf")
msp = doc.modelspace()
cut_doc = ezdxf.new("R12")
cut_msp = cut_doc.modelspace()
for entity in msp.query("LWPOLYLINE"):
if entity.is_closed:
# Copy to new document
cut_msp.add_entity(entity.copy())
cut_doc.saveas("laser_cut_ready.dxf")
Practical Tips
- Export R12 for maximum compatibility — almost nothing outside AutoCAD needs features above R12 for 2D work
- LWPOLYLINE over POLYLINE — LWPOLYLINE is more efficient (fewer group codes), universally supported, and is the standard for 2D closed outlines
- Units trap: DXF
$INSUNITScodes: 0=unitless, 1=inches, 4=mm, 6=meters. Always check units when importing — a drawing in inches opened assuming mm will be 25.4× the wrong size - Layer 0 is special — entities on layer 0 inside a block inherit the inserting layer's properties (color, linetype). Don't use layer 0 for regular entities outside blocks.
- ezdxf for Python is the only actively maintained pure-Python DXF library — use it for all DXF read/write tasks
- Validate with ezdxf audit:
doc.audit()returns a list of DXF integrity issues before saving
DXF's open specification, human-readable ASCII format, and universal support across 40+ years of CAD and fabrication software make it the definitive interchange format for 2D technical drawing data.
Related conversions
Frequent conversions across the catalogue: