Creating a blind or buried via with pcbnew's Python API

Published on September 19, 2026 by leZ

Turn a regular through via into a blind or buried via, restricted to certain inner layers, by script — with pcbnew or KiCad's IPC API.

Blind via from F.Cu to In1.Cu on a 4-layer board, created by a pcbnew Python script in KiCad
The blind via, drawn with the F.Cu and In1.Cu colours.

The via creation tutorial creates a through via, drilled all the way across the board. On a multi-layer board, a blind via (from an outer layer to an inner one) or a buried via (between two inner layers only) saves routing density without drilling through the whole thickness.

Choosing the via type and its layer pair

SetViaType changes the type, then SetLayerPair sets the two layers the via is drilled between:

import pcbnew

board = pcbnew.GetBoard()
from pcbnew import PCB_VIA, VIATYPE_BLIND, VECTOR2I, FromMM, F_Cu, In1_Cu

via = PCB_VIA(board)
via.SetPosition(VECTOR2I(FromMM(30), FromMM(20)))
via.SetViaType(VIATYPE_BLIND)
via.SetLayerPair(F_Cu, In1_Cu)  # blind: from an outer layer to an inner one
board.Add(via)

⚠️ There is no VIATYPE_BLIND_BURIED: pcbnew always distinguishes VIATYPE_BLIND and VIATYPE_BURIED.

Same idea, with dedicated properties for the type and the layer pair — the latter is set via the padstack, not a direct layer_pair property. ViaType does offer a generic VT_BLIND_BURIED value, but it doesn’t survive a server round-trip: KiCad re-evaluates it and silently replaces it with VT_BLIND or VT_BURIED based on the actual layer pair given. Might as well use the precise value directly, just like on the pcbnew side:

from kipy import KiCad
from kipy.board_types import Via, ViaType
from kipy.geometry import Vector2

board = KiCad().get_board()

via = Via()
via.position = Vector2.from_xy_mm(30, 20)
via.type = ViaType.VT_BLIND
via.padstack.drill.start_layer = board.get_layer_by_name("F.Cu")
via.padstack.drill.end_layer = board.get_layer_by_name("In1.Cu")
board.create_items(via)

⚠️ Tested: assigning ViaType.VT_BLIND_BURIED and then reading the created via back returns VT_BLIND — no error, but the value you set isn’t the one actually stored. VT_BLIND and VT_BURIED, on the other hand, persist exactly as assigned.

Try it below: switch the type to see the via’s cross-section change based on which layers it spans.

via.SetViaType(VIATYPE_THROUGH)
via.SetLayerPair(F_Cu, B_Cu)
F.CuIn1.CuIn2.CuB.Cu

Going further

A buried via (between two inner layers, never reaching F.Cu or B.Cu) follows the same principle: just pick a pair of inner layers, for example In1_Cu/In2_Cu (VIATYPE_BURIED on the pcbnew side, ViaType.VT_BURIED on the IPC side — verified on a 10-layer board). These via types usually require a specific layer stackup and a fabricator that supports them — check fabrication rules before relying on them heavily.