Fusion 360 APIPythonFusion 360 · bundled Python interpreterMIT licenseIntermediate
Sweep a Fusion 360 parameter and batch-export each variant to STL
A parametric model already knows how to become every size variant you'll ever need — the tedious part is babysitting Fusion through a dozen manual edits and Save-As-STLs. This script sweeps a named user parameter across a list of values, lets Fusion recompute after each change, and exports every variant to its own STL — then puts the parameter back exactly where it found it.
Before you run it
- A Fusion 360 design with a user parameter already defined (Modify → Change Parameters)
- Run from Utilities → Add-Ins → Scripts and Add-Ins (Shift+S) → Create
- Edit
PARAM_NAME,VALUES, andOUT_FOLDERbefore running
The code
"""Sweep a Fusion 360 user parameter and export each variant to STL.
Run from Utilities -> Add-Ins -> Scripts and Add-Ins (Shift+S).
Edit PARAM_NAME, VALUES, and OUT_FOLDER, then run.
"""
import os
import traceback
import adsk.core
import adsk.fusion
PARAM_NAME = "PlateWidth" # must already exist as a user parameter
VALUES = ["60 mm", "80 mm", "100 mm"] # one export per value, Fusion's own unit syntax
OUT_FOLDER = "C:\\FusionExports\\" # must end with a backslash
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
design = adsk.fusion.Design.cast(app.activeProduct)
root = design.rootComponent
param = design.userParameters.itemByName(PARAM_NAME)
if not param:
ui.messageBox(f"No user parameter named '{PARAM_NAME}' in this design.")
return
original = param.expression
exporter = design.exportManager
exported, failed = 0, 0
for value in VALUES:
param.expression = value
adsk.doEvents() # let Fusion finish recomputing before we export
safe_name = value.replace(" ", "")
path = os.path.join(OUT_FOLDER, f"{PARAM_NAME}_{safe_name}.stl")
options = exporter.createSTLExportOptions(root, path)
options.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementMedium
if exporter.execute(options):
exported += 1
else:
failed += 1
param.expression = original # leave the document the way we found it
ui.messageBox(f"{exported} STL(s) exported, {failed} failed.\n{OUT_FOLDER}")
except:
if ui:
ui.messageBox(f"Failed:\n{traceback.format_exc()}")What you get
What you get
C:\FusionExports\
├── PlateWidth_60mm.stl
├── PlateWidth_80mm.stl
├── PlateWidth_100mm.stl
└── ...
3 STL(s) exported, 0 failed.
C:\FusionExports\How it works
design.userParameters.itemByName(PARAM_NAME)is the entire trick — Fusion models are parametric by default, so changing one parameter's.expressionand letting the model recompute is cheaper and more reliable than modeling N separate variants by hand.adsk.doEvents()after changing the parameter is load-bearing: Fusion's recompute isn't necessarily finished the instant.expressionreturns, and exporting before it settles can capture the previous geometry.- The original expression is restored at the end — the script leaves the document exactly as it found it, the same discipline as reactivating no particular configuration when the SolidWorks batch-STEP macro finishes.
createSTLExportOptions(root, path)with an explicit path is what makes this headless — the same call without a path pops Fusion's own Save dialog instead.
Gotchas & honest limits
- The Fusion API's internal unit is the centimeter, but
UserParameter.expressionaccepts unit strings like"80 mm"directly — this script leans on that instead of hand-converting, unlike rawValueInput.createByRealcalls that need/10everywhere. - This assumes
PARAM_NAMEalready exists as a user parameter in the design — the script checks and messages, but doesn't create one for you. - STL is a mesh export — for exact geometry to hand a variant to someone else's CAD, swap
createSTLExportOptionsforcreateSTEPExportOptions; the rest of the loop is unchanged. - Recomputing and exporting many variants in a loop is slow on a heavy assembly — this is the right pattern for a handful of sizes, not hundreds.
Goes deeper
Want this adapted to your shop — or built into a real tool?
Samples are the free 80%. The last 20% is the part I do for a living.