OpenSCAD cheat sheet: every shape, function and operator
This OpenSCAD cheat sheet lists every built-in shape, transform, boolean, operator, special variable and function on one page, with the defaults you actually need to remember. It follows the stable 2021.01 release and flags newer development-snapshot features separately. Click any chip to copy it.
- Smooth curves:
$fa = 1; $fs = 0.4;at the top of the file. - A through-hole:
difference() { cube([40, 20, 4]); translate([10, 10, -1]) cylinder(h = 6, d = 3.4); } - A row of copies:
for (x = [0 : 10 : 40]) translate([x, 0, 0]) cube(5); - Rounded corners:
hull()four cylinders, oroffset(r = 3)a 2D shape before extruding. - A 2D shape you can print:
linear_extrude(height = 3) square([20, 10]);
Everything here works in the latest stable release, OpenSCAD 2021.01, unless it's tagged with a
version or listed under snapshot-only features. Snapshots are the nightly builds and the
2026.10 test builds on openscad.org. PrintPal's browser editor runs a 2025 snapshot with the Manifold engine and
roof() switched on. It has no textmetrics() or 3MF import and uses a single built-in font for text().
OpenSCAD syntax basics
Variables, modules, functions, filesx = 10;Assignment. One value per scope: the last one winsx = cond ? a : b;Conditional valuef = function (x) x * 2;Function literal (2021.01+)module name(a, b = 2) { … }Define a module (makes geometry)function name(a) = a * 2;Define a function (returns a value)name(1, b = 3);Call: positional args first, then namedinclude <file.scad>Paste the whole file in, including its variablesuse <file.scad>Import only its modules and functions// note /* block */Commentsundef true false PIBuilt-in constants (PI ≈ 3.14159)OpenSCAD default values worth memorising
What you get when you leave an argument out| Call or variable | Default | Why it matters |
|---|---|---|
cube() | size 1, center = false | Grows from the origin into +X, +Y, +Z |
sphere() | r = 1 | Centred on the origin. Poles are flat, so it's slightly shorter than its diameter |
cylinder() | h = 1, r1 = r2 = 1, center = false | Positional order is h, r1, r2, center |
circle() / square() | r = 1 / size 1 | Squares sit on the origin unless center = true |
linear_extrude() | height = 100, twist = 0, scale = 1 | Forget the height and you get a 100 mm tower |
rotate_extrude() | angle = 360, convexity = 2 | The 2D profile must stay on one side of the Y axis |
text() | size = 10, font = "Liberation Sans", halign = "left", valign = "baseline" | Capital letters come out about size mm tall |
import("x.svg") | dpi = 72 | Applies to unitless SVGs. Pass dpi = 96 for files drawn at 96 px per inch |
offset() | r = 1 | Pass either r or delta |
polygon() / polyhedron() | convexity = 1 | Raise it if the preview shows see-through glitches |
$fn | 0 (off) | When above 0, sets an exact segment count and overrides $fa/$fs |
$fa / $fs | 12° / 2 mm | Every segment is at least 12° and at least 2 mm, so small holes get very few sides |
| Minimum segments | 5 | With $fn = 0, even a tiny circle gets at least 5 sides |
OpenSCAD operators
Arithmetic, comparison, logical| Operator | Meaning | Operator | Meaning |
|---|---|---|---|
a + b | Add (element-wise on vectors) | a < b | Less than |
a - b | Subtract | a <= b | Less or equal |
a * b | Multiply (dot product for two vectors) | a == b | Equal |
a / b | Divide | a != b | Not equal |
a % b | Modulo (remainder) | a >= b | Greater or equal |
a ^ b | Power (2021.01+) | a > b | Greater than |
a && b | Logical AND | a || b | Logical OR |
!a | Logical NOT | c ? a : b | Conditional |
"a" + "b" and undef + 1 give undef with a warning, not a string or a number. Use str("a", "b") to join text.OpenSCAD special variables ($fn, $fa, $fs, $t)
Dollar variables pass down into every call| Variable | Default | What it controls |
|---|---|---|
$fn | 0 | Exact number of segments for circles, spheres and cylinders when above 0 (minimum 3). The manual advises staying at or below 128. |
$fa | 12 | Minimum angle per segment, in degrees. Smaller means smoother big curves. |
$fs | 2 | Minimum segment length in mm. Smaller means smoother small curves. |
$t | 0 | Animation time. It runs from 0 up to, but never reaching, 1. |
$preview | n/a | true in an F5 preview, false in an F6 render or command-line export (2019.05+). |
$children | n/a | How many children were passed to the current module. |
$vpr $vpt $vpd | n/a | Viewport rotation, translation and distance. Read them, or set them to aim the camera. |
$vpf | n/a | Viewport field of view (2021.01+). |
$parent_modules | n/a | Depth of the module call stack. Use with parent_module(i). |
Segment count when $fn is 0: max(min(360 / $fa, 2πr / $fs), 5), rounded up. With the defaults that's 5 segments for r = 1.5 and 30 for r = 10.
Debug modifier characters
Put one in front of any statement*Disable: ignore this subtree!Root: show only this subtree#Debug: highlight it in preview, still part of the model%Background: ghosted in preview, left out of the modelThe # and % highlights only appear in desktop OpenSCAD's F5 preview. # on a difference() cutter is the fastest way to see where a hole really is.
2D shapes
Flat shapes in the XY plane| Call | Description |
|---|---|
circle(r) / circle(d = …) | Circle centred on the origin |
square(size, center = false) | Square or rectangle. size is a number or [x, y] |
polygon(points, paths, convexity) | Any outline. Optional paths cut holes |
text(t, size, font, halign, valign, spacing, direction, language, script) | Text outline from a font |
import("file.svg") / import("file.dxf") | 2D file import. SVG also takes center and dpi |
projection(cut = false) | 3D to 2D silhouette. cut = true slices at z = 0 |
offset(r | delta, chamfer = false) | Grow or shrink a 2D shape, rounded or sharp |
2D shapes need an extrusion before you can print them. See 2D shapes and extrusion.
3D shapes and extrusions
Solid building blocks| Call | Description |
|---|---|
cube(size, center = false) | Box. size is a number or [x, y, z] |
sphere(r) / sphere(d = …) | Ball centred on the origin. d must be named |
cylinder(h, r | d, center = false) | Cylinder standing on z = 0 |
cylinder(h, r1, r2) / cylinder(h, d1 = …, d2 = …) | Cone or truncated cone |
polyhedron(points, faces, convexity) | Any closed solid. Faces list points clockwise seen from outside |
import("file.stl" | "file.off" | "file.amf" | "file.3mf") | Mesh import (AMF and 3MF since 2019.05) |
surface(file, center, invert, convexity) | Heightmap from a PNG or DAT file |
linear_extrude(height, center, convexity, twist, slices, scale) | Push a 2D shape straight up, optionally twisting or tapering |
rotate_extrude(angle = 360, convexity = 2) | Spin a 2D profile around the Z axis |
Details, pitfalls and print-ready hole sizes: 3D primitives reference.
Transformations
Move, rotate, scale, mirror, colour| Call | Description |
|---|---|
translate([x, y, z]) | Move by a vector |
rotate([x, y, z]) | Rotate in degrees about the origin: X first, then Y, then Z |
rotate(a, [x, y, z]) | Rotate a° about an axis. rotate(a) alone turns around Z |
scale(s) / scale([x, y, z]) | Multiply sizes. 1 leaves an axis alone |
resize([x, y, z], auto = false) | Stretch to an exact size. 0 keeps an axis, auto = true scales it to match |
mirror([x, y, z]) | Mirror across the plane through the origin with that normal |
multmatrix(m) | Apply a 4×4 (or 3×4) transform matrix |
color("name" | "#rrggbb" | [r, g, b, a], alpha) | Preview colour only (hex strings 2019.05+). STL has no colour |
Boolean operations, hull and minkowski
Combine shapesunion() { … }Merge children (implicit at top level)difference() { A(); B(); }First child minus every later childintersection() { … }Keep only shared volumehull() { … }Tightest convex skin around the childrenminkowski() { … }Grow one child by the shape of the other. Rounds edges, but slowrender(convexity) { … }Fully render a subtree during previewWhy cutters should overshoot and how to keep booleans fast: boolean operations guide.
Lists and vectors
Indexing and vector mathsv = [10, 20, 30];Make a list (any types, can nest)v[0]10. Indexes start at 0, out of range gives undefv.x v.y v.zFirst, second, third elementlen(v)3. Also works on stringsconcat([1, 2], [3])[1, 2, 3]. Lists only, use str() for text[1, 2] + [3, 4][4, 6], element-wise[1, 2, 3] * [4, 5, 6]32, the dot productlookup(2.5, [[0, 0], [5, 10]])5, linear interpolation in a tableList comprehensions
Build lists in one expression[for (i = [0 : 3]) i * i][0, 1, 4, 9][for (i = [1 : 6]) if (i % 2 == 0) i][2, 4, 6], filtered[for (i = [0 : 3]) if (i % 2 == 0) i else -i][0, -1, 2, -3] (2019.05+)[for (i = [0 : 2]) let (a = i * 120) [cos(a), sin(a)]]Three points on a unit circle[0, each [1, 2], 3][0, 1, 2, 3], spliced in (2019.05+)[for (r = [[1, 2], [3]]) each r][1, 2, 3], flattened one level[for (i = 0; i < 4; i = i + 1) i][0, 1, 2, 3], C-style (2019.05+)[for (c = "abc") c]["a", "b", "c"]Flow control: for, if, let
Repeat, choose, name thingsfor (i = [0 : 10]) …0 to 10 inclusive, step 1for (i = [0 : 2 : 10]) …Step 2: 0, 2, … 10for (i = [10 : -2 : 0]) …Count down with a negative stepfor (p = [[0, 0], [5, 5]]) …Loop over a listfor (x = [0 : 2], y = [0 : 2]) …Nested: 9 copiesintersection_for (i = [0 : 2]) …Intersect the copies instead of mergingif (c) { … } else { … }Choose geometrylet (r = 5) { … }Local constants (module form 2019.05+)assert(h > 0, "h must be positive");Stop with an error (2019.05+)echo("h =", h);Print to the consoleScoping rules, recursion and when a loop can't do what you want: OpenSCAD language reference.
Type test functions
Check what a value is (2019.05+)is_undef(x)Is it undef?is_bool(x)true or false?is_num(x)A number?is_string(x)A string?is_list(x)A list? (false for ranges)is_function(x)A function literal? (2021.01+)String and utility functions
Text, search, version, modulesstr("M", 3)"M3", joins anything into a stringlen("M3x10")5search("x", "M3x10")[2], index of the matchchr(65) ord("A")"A" and 65 (ord 2019.05+)version() version_num()[2021, 1, 0] and 20210100 on 2021.01children() children(i)Draw the shapes passed into a moduleparent_module(i)Name of a calling modulerands(min, max, n, seed)List of n random numbers (seed makes it repeatable)Math functions
Trig in degrees, scalar and vector maths| Trigonometry (degrees) | Numbers | Vectors |
|---|---|---|
sin(a) cos(a) tan(a) | abs(x) sign(x) | norm(v) (length) |
asin(x) acos(x) atan(x) | floor(x) ceil(x) round(x) | cross(a, b) |
atan2(y, x) | ln(x) natural, log(x) base 10, exp(x) | min(v) max(v) |
pow(b, e) · sqrt(x) · min(a, b, …) · max(a, b, …) · round(-2.5) is -3 (halves round away from zero) | ||
sin(30) is 0.5, and atan2(1, 1) returns 45. To pass an angle you have in
radians, convert it first: rad * 180 / PI.
What does echo(sin(90)); print in OpenSCAD?
90 is read as degrees, and sin(90°) is 1. 0.894 is what you'd get for 90 radians, which is the classic mistake when porting code from Python or JavaScript.
Snapshot-only features (not in 2021.01)
Need a nightly or 2026.10 test build| Feature | What it does |
|---|---|
| Manifold geometry engine | Much faster renders. Turn it on in Preferences, or pass --backend=manifold on the command line |
roof(method = "straight" | "voronoi") | Turns a 2D outline into a 45° sloped roof solid |
fill() | Removes the holes from a 2D shape |
textmetrics(), fontmetrics() | Measure text and fonts as data, for example to size a label plate |
linear_extrude(v = [x, y, z], segments = n) | Extrude along a direction vector, with extra segments |
rotate_extrude(start = a) | Start angle for a partial sweep |
text(em = …) | Size text by the font's em square instead of size |
import("file.obj") | OBJ mesh import |
& | ~ << >> | Bitwise operators on integers |
In some snapshots these sit behind experimental switches under Preferences → Features. Code that uses them won't parse or run in 2021.01.
Copy-paste OpenSCAD examples
Rounded plate with minkowski()
// 40 × 30 × 4 mm plate with 3 mm round corners
minkowski() {
cube([34, 24, 3]); // 40 - 2×3, 30 - 2×3, 4 - 1
cylinder(r = 3, h = 1, $fn = 32);
}
Hollow tube with a 2 mm wall
difference() {
cylinder(h = 40, d = 20, $fn = 64);
translate([0, 0, -1])
cylinder(h = 42, d = 16, $fn = 64);
}
Staggered hex studs
for (x = [0 : 10 : 50], y = [0 : 10 : 40])
translate([x, y + (x / 10 % 2 == 1 ? 5 : 0), 0])
cylinder(h = 3, d = 8, $fn = 6);
Solid vase blank with rotate_extrude()
// Print it in vase (spiral) mode
rotate_extrude($fn = 120)
polygon([[0, 0], [20, 0], [15, 20], [25, 50], [12, 60], [0, 60]]);
Frequently asked questions
Is there an official OpenSCAD cheat sheet?
Yes. openscad.org/cheatsheet is the official one-page reference, and each entry links to the OpenSCAD User Manual on Wikibooks. This page covers the same built-ins and adds defaults, version notes, worked examples and common pitfalls.
Does OpenSCAD use degrees or radians?
Degrees. sin(90) is 1, rotate([0, 0, 45]) turns 45°, and inverse functions such as atan2(1, 1) return degrees (45). If you have an angle in radians, multiply it by 180 / PI before passing it in.
What are the default $fn, $fa and $fs values in OpenSCAD?
$fn = 0 (off), $fa = 12 degrees and $fs = 2 mm. With those defaults every circle gets at least 5 segments, so a 3 mm hole is a pentagon. Setting $fa = 1 and $fs = 0.4 gives print-quality curves, and a 3 mm hole then gets 24 segments.
What is the difference between include and use in OpenSCAD?
include <file.scad> works as if you pasted the file in: its modules, functions, variables and any top-level geometry all come along. use <file.scad> imports only modules and functions and ignores the file's top-level code. BOSL2 asks for include <BOSL2/std.scad>.
Related articles
Further reading
Tools for thisAll tools
Watch it doneVideo library
Thanks! We read every note and use them to decide what to update next.