Most 3D tools ask you to push and pull geometry with a mouse. OpenSCAD does not. You write a script — and the script is the model. No file format that diverges from the source of truth, no “I moved something by hand and now I can’t reproduce it”, no .blend file that is a black box. Just text that describes a solid object, and a renderer that turns it into a mesh.
What is OpenSCAD?
OpenSCAD is a script-only parametric 3D CAD modeller. It functions as a “3D compiler”: you describe your object using geometric primitives and boolean operations, and OpenSCAD evaluates the script to produce an exact solid mesh that you can export for 3D printing, CNC machining, or further CAD work.
“OpenSCAD is a software for creating solid 3D CAD objects. It is free software and available for Linux/UNIX, Windows and Mac OS X. Unlike most free software for creating 3D models, OpenSCAD focuses on the CAD aspects rather than the artistic aspects of 3D modelling.”
OpenSCAD Source Code on GitHub OpenSCAD Website OpenSCAD Documentation
What makes it different from every other 3D tool
- 📝 Code is the model —
.scadfiles are plain text;git difftells you exactly what changed between versions - 🔁 Perfect reproducibility — the same script always produces the exact same geometry
- 🔩 Parametric by nature — change a variable at the top and the entire model updates
- 🖥️ Headless CLI — export STL/3MF/SVG from a shell script or CI pipeline with zero GUI
- 🧮 CSG-based — union, difference, intersection of solids; impossible to produce non-watertight meshes from valid geometry
- ⚖️ GPL v2 licensed — completely free, forever
How OpenSCAD Works
OpenSCAD evaluates your script in a pipeline:
.scad script
→ Lexer (Flex) + Parser (Bison) → AST
→ Evaluator → values and context
→ CSG Tree builder → geometry nodes
→ CGAL / Manifold → exact solid mesh
→ Export → STL, 3MF, SVG, PNG…
The preview window uses OpenCSG — a fast screen-space renderer that gives you interactive feedback while you type. The export path uses CGAL (the Computational Geometry Algorithms Library) or Manifold for exact boolean operations on solid geometry. Both backends produce correct results; CGAL is more established, Manifold is faster for certain operations.
The OpenSCAD Language
Building shapes
// 3D primitives
cube([40, 20, 10], center=true);
sphere(r=5, $fn=100); // $fn = facet count → smoothness
cylinder(h=20, r=5, $fn=60);
// 2D primitives (used for extrusions)
square([30, 15], center=true);
circle(r=8, $fn=100);
polygon(points=[[0,0],[20,0],[10,15]]);
text("Hello", size=8, font="Liberation Sans");
Combining shapes with CSG
difference() {
cube([40, 30, 15], center=true); // the base
cylinder(h=20, r=6, center=true); // the hole
}
union() {
cube(10);
translate([8, 0, 0]) sphere(r=6);
}
intersection() {
sphere(r=10);
cube(14, center=true);
}
Transformations
translate([10, 0, 0]) cube(5);
rotate([0, 0, 45]) cube(10, center=true);
scale([2, 1, 0.5]) sphere(r=5);
mirror([1, 0, 0]) cylinder(h=10, r=3);
Making it parametric
// Parameters at the top
length = 80; // mm
width = 40;
height = 10;
hole_r = 5;
wall = 3;
// The model references them
difference() {
cube([length, width, height]);
translate([length/2, width/2, -1])
cylinder(h=height+2, r=hole_r, $fn=60);
}
Change hole_r = 8 — the hole updates. Change length = 120 — the whole part scales. This is the parametric promise, delivered in plain text.
Modules — reusable geometry blocks
module rounded_box(dims, r=2, $fn=32) {
minkowski() {
cube(dims - [r*2, r*2, r*2], center=true);
sphere(r);
}
}
rounded_box([60, 40, 20]);
rounded_box([30, 30, 10], r=4);
Loops, functions, and list comprehensions
// Arrange copies in a grid
for (x = [0:3], y = [0:3])
translate([x*20, y*20, 0]) sphere(r=4);
// Function
function area(r) = PI * r^2;
// Anonymous function (2021.01+)
let(clamp = function(v, lo, hi) min(max(v, lo), hi))
echo(clamp(150, 0, 100));
// List comprehension → array of positions
pts = [for (a = [0:36:360]) [cos(a)*20, sin(a)*20]];
polygon(pts);
Extrusions
// Extrude a 2D shape into 3D
linear_extrude(height=15, twist=90, scale=0.5)
square(10, center=true);
// Rotate a 2D profile around the Z axis
rotate_extrude(angle=270, $fn=120)
translate([15, 0]) circle(r=5);
The Customizer
OpenSCAD includes a Customizer panel that turns annotated variables into sliders, checkboxes, and text inputs — without touching the code:
/* [Main dimensions] */
// Total length (mm)
length = 80; // [20:200]
// Wall thickness
wall = 3; // [1:0.5:8]
// Add mounting holes?
holes = true; // checkbox
// Label text
label = "v1"; // text field
/* [Hidden] */ // params below this are not shown in Customizer
debug = false;
Presets are saved as JSON files and can be fed back to the CLI for batch export:
openscad -p variants.json -P "Large" -o large.stl bracket.scad
openscad -p variants.json -P "Small" -o small.stl bracket.scad
Installing OpenSCAD
Desktop (interactive use)
Linux
AppImage — most reliable for the current release:
wget https://github.com/openscad/openscad/releases/download/openscad-2021.01/OpenSCAD-2021.01-x86_64.AppImage
chmod +x OpenSCAD-*.AppImage
./OpenSCAD-*.AppImage
Flatpak:
flatpak install flathub org.openscad.OpenSCAD
Package manager:
sudo apt install openscad # Ubuntu / Debian
sudo pacman -S openscad # Arch
sudo dnf install openscad # Fedora
macOS and Windows
Download from openscad.org/downloads .
- macOS:
.dmgdisk image, orbrew install openscad - Windows:
.exeinstaller
Headless server (no display required)
OpenSCAD’s CLI works without a display server. Install the package or AppImage on any Linux server:
# Debian / Ubuntu
sudo apt install openscad
# Verify headless export works
echo "sphere(r=10);" | openscad -o test.stl --stdin
Headless Automation
This is where OpenSCAD shines for self-hosters and DevOps engineers.
Basic export
# STL for 3D printing
openscad -o part.stl design.scad
# 3MF (richer format — colours, metadata)
openscad -o part.3mf design.scad
# PNG preview with custom camera
openscad -o preview.png \
--camera=0,0,0,45,0,30,250 \
--imgsize=1920,1080 \
design.scad
Parametric variants from the command line
# Override any top-level variable
openscad -D 'length=50' -D 'wall=2' -o thin_50.stl bracket.scad
openscad -D 'length=80' -D 'wall=4' -o thick_80.stl bracket.scad
# Export multiple formats in one pass
openscad \
-D 'size=60' \
-o part.stl \
-o part.3mf \
-o preview.png \
design.scad
Animation frame rendering
Use the special $t variable (ranges 0–1 over all frames):
// Spinning animation
rotate([0, 0, $t * 360]) cube([40, 10, 10], center=true);
# Render 60 frames → frame_00001.png … frame_00060.png
openscad -o frame_%05d.png --animate=60 spinner.scad
# Distribute across two machines
openscad -o frame_%05d.png --animate=60 --animate-sharding=0/2 spinner.scad
openscad -o frame_%05d.png --animate=60 --animate-sharding=1/2 spinner.scad
Running in Docker
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y openscad && \
rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["openscad"]
docker build -t openscad-headless .
docker run --rm \
-v "$PWD":/work \
openscad-headless \
-D 'size=40' \
-o /work/output.stl \
/work/design.scad
CI/CD integration
Because OpenSCAD returns a non-zero exit code on errors, it integrates cleanly into any pipeline:
# GitHub Actions example
- name: Export STL
run: openscad -o part.stl -D 'wall=3' bracket.scad
- name: Upload artefact
uses: actions/upload-artifact@v4
with:
name: bracket
path: part.stl
Every commit that modifies .scad files triggers a fresh export — the STL in your release artefacts is always in sync with the source.
Why Git + OpenSCAD is the right combination
A Blender .blend or FreeCAD .FCStd file is a binary blob. git diff shows you that it changed; it cannot show you what changed.
An OpenSCAD .scad file is plain text. git diff shows you the exact parameter you adjusted, the line you added, the module you renamed. Code review for mechanical design works the same way as code review for software.
- wall = 2;
+ wall = 3; // increased for print reliability
This is why OpenSCAD has become the standard format on Thingiverse, Printables, and Makerworld for parametric parts — the source file is the deliverable, not a compiled mesh.
File Format Support
| Category | Input | Output |
|---|---|---|
| Native | .scad |
.scad |
| 3D mesh | STL, OFF, 3MF, AMF, OBJ | STL, OFF, 3MF, AMF, OBJ |
| 2D profile | DXF, SVG | DXF, SVG |
| Image | — | PNG |
| Document | — | |
| Debug | — | CSG, AST |
Conclusion
OpenSCAD occupies a unique and irreplaceable position in the FOSS toolchain: it is the only mainstream CAD tool where the model is the code. That single design decision makes it the right choice for makers who value reproducibility, engineers who want version control, and DevOps people who want to generate geometry from a CI pipeline.
It does not replace FreeCAD for complex assemblies, technical drawings, or FEM analysis. It does not replace Blender for organic shapes, rendering, or animation. But for parametric mechanical parts destined for a 3D printer or CNC mill — especially ones that need to be shared, versioned, and customised — it is the best tool in the FOSS ecosystem.
Related tools worth knowing:
- CadQuery — Python-first CSG using OpenCASCADE; same “code is the model” philosophy but with full Python and a more capable geometry kernel
- FreeCAD — GUI parametric CAD with Python API; better for complex assemblies, technical drawings, FEM; steeper learning curve
- ImplicitCAD — Haskell-based CSG with smooth implicit surfaces; OpenSCAD-compatible syntax
- SolveSpace — sketch-and-constraint parametric CAD; lightweight, precise, good for 2D-driven 3D
Frequently Asked Questions
Can OpenSCAD import STEP or IGES files?
Not directly. STEP and IGES require the OpenCASCADE geometry kernel, which OpenSCAD does not include. If you need to work with STEP files, import them in FreeCAD, export to STL, and then use that STL as a reference solid in OpenSCAD with the import() statement.
How do I control the smoothness of spheres and cylinders?
The $fn, $fs, and $fa special variables control discretisation. $fn=100 gives a 100-sided polygon approximation. Set it globally at the top of your script or locally per primitive. High values slow down rendering; keep it low during development and raise it for final export.
What is the Manifold backend and should I use it?
Manifold is a newer, faster geometry kernel added as an alternative to CGAL for some operations (particularly Minkowski sum and final mesh triangulation). Enable it in Preferences → Advanced → Backend. It is faster than CGAL for most operations and produces cleaner output, but CGAL remains the default for stability. Both are included in current builds.
Can I use external libraries in my scripts?
Yes — the use <library.scad> and include <library.scad> statements import external .scad files. The MCAD library (included as a submodule) provides gears, screws, and mechanical components. BOSL2, Dotscad, and NopSCADlib are popular community libraries — place them in your OpenSCAD library path.
How does OpenSCAD compare to CadQuery?
Both are code-first parametric CAD tools. OpenSCAD uses CSG boolean operations on discretised meshes (approximations). CadQuery uses OpenCASCADE’s BREP kernel — exact boundary representation — which is more powerful but requires Python. OpenSCAD is simpler to learn; CadQuery is more capable for complex geometry. Many makers start with OpenSCAD and graduate to CadQuery for demanding projects.
Is there a way to render OpenSCAD in a browser?
Yes — OpenSCAD has a WebAssembly build. Projects like OpenSCAD playground run OpenSCAD entirely in the browser, no installation required. This is also how Thingiverse’s Customizer feature works.
Comments