Routing a trace with pcbnew's Python API
Create a copper trace between two points, with a defined width, by script — with pcbnew or KiCad's IPC API.

Routing a bundle of identical traces by hand (a data bus, a series of connections to a connector) is repetitive and prone to width mistakes. Scripting trace creation guarantees a reproducible width and path — the starting point for any homemade auto-router.
A track (and a via) created by script, filmed live in KiCad (1:16):
Creating the track
Instantiate a PCB_TRACK object attached to the board, then add it:
import pcbnew
board = pcbnew.GetBoard()
from pcbnew import PCB_TRACK
track = PCB_TRACK(board)
board.Add(track)With the IPC API, you instantiate a blank Track object; it doesn’t exist on the board until it’s explicitly created:
from kipy import KiCad
from kipy.board_types import Track
kicad = KiCad()
board = kicad.get_board()
track = Track()Setting the path, width, and layer
The track’s start and end are set in internal units, width and layer separately:
from pcbnew import VECTOR2I, FromMM, F_Cu
track.SetStart(VECTOR2I(FromMM(10), FromMM(20)))
track.SetEnd(VECTOR2I(FromMM(40), FromMM(20)))
track.SetWidth(FromMM(0.25))
track.SetLayer(F_Cu)Start and end are set in millimeters via Vector2.from_xy_mm, but width is a raw nanometer integer that needs an explicit from_mm conversion:
from kipy.geometry import Vector2
from kipy.util.units import from_mm
track.start = Vector2.from_xy_mm(10, 20)
track.end = Vector2.from_xy_mm(40, 20)
track.width = from_mm(0.25)
track.layer = board.get_layer_by_name("F.Cu")⚠️ track.layer expects a BoardLayer value, not a string: track.layer = "F.Cu" raises a ValueError. get_layer_by_name does the conversion.
Try it below: adjust length and width to see the trace change on the board.
Connecting the track to a net
Just like a via, the track needs to be attached to an existing net:
track.SetNet(board.FindNet("GND"))On the IPC API side, the net is referenced directly by name. This is also the point, once every property is set, where the track is actually created on the board:
from kipy.board_types import Net
track.net = Net(name="GND")
board.create_items(track)Going further
This skeleton generalizes to a loop that automatically connects a series of pads together — the basis for a small homemade router for repetitive topologies (buses, connector rows), instead of drawing every trace by hand.