Skip to main content

part2kicad

Type an LCSC part number and get a KiCad part you can hand to a fab house: the official KiCad symbol where one exists, a standard footprint that was measured before it was swapped in, real pin types so KiCad's electrical rule check has something to work with — and a report that says, field by field, where every value came from.

pip install part2kicad
cd my-board
part2kicad add C93119
LM393M (C93119) → my-board.kicad_sym
  8 pins in 3 units
  Footprint my-board:SOIC-8_L4.9-W3.9-P1.27-LS6.0-BL, 8 pads
  3D model ${KIPRJMOD}/my-board.3dshapes/SOIC-8_L4.9-W3.9-P1.27-LS6.0-BL.step
  Fetched on 2026-08-15
  14 rules checked, 6 violated, 0 added
  ! Taking the official symbol over also exchanged 8 pin names — the numbers agree on
    both sides, so nothing moves electrically: 1 '1' → '', 2 '2' → '-', 3 '3' → '+', …

Open the schematic, press A, and the part is in the list. No download folder, no library table to edit, no files to copy around.

The six violations in that last line are not a failure to hide — they are the reason to use this tool at all. All six sit on the footprint, which this part keeps because the official candidate misses its pads by 0.2498 mm and 0.20 mm is what the tolerance allows. The report says exactly that, with the figures.

What a part looks like before and after

C93119 is a plain LM393 comparator, and it is the whole argument in one part. This is what changes when it goes through part2kicad — measured on 2026-08-15, not estimated:

as the source delivers it after part2kicad add
Units one flat block, 8 pins 3 units — two comparators and a supply block
Pin types 8 × unspecified 2 × power_in, 4 × input, 2 × open_collector
Rule violations 10 of 14 6 of 14, all of them on the footprint
Electrical rule check nothing to check catches a comparator output tied to +3V3

That last row was run by hand in KiCad, in the order that makes it mean something: the rule check was first made silent with PWR_FLAG on both supply nets, and only then was the deliberate mistake introduced. Without that step the check only proves that KiCad says something.

An RP2040 in a QFN-56 tells the same story from the other end. Its converted footprint broke 6 of 9 footprint rules; after the official QFN-56-1EP_7x7mm_P0.4mm was measured against it and swapped in, the count is 0. Its symbol arrives with 51 of 57 pins off the 2.54 mm grid, and comes out with none.

What it does

It takes the official KiCad part over when there is one. For the symbol it looks for the manufacturer part number in your installed KiCad libraries — exact name first, then the name with a suffix trimmed, then the package family. extends is resolved, so you get the real body and not a stub. The taken-over symbol keeps your name and your provenance fields, and the report names the library, the symbol, whatever suffix was cut off, and the KiCad version it came from.

It swaps the footprint only when the geometry agrees. The package name chooses the candidate; the measurement vetoes it. Pad hull, lead span, largest pad and pad pitch are compared, and anything off by more than 0.20 mm keeps the source drawing. Drill diameter and grid are hard gates with no tolerance at all — a 10 mm electrolytic that matched its official candidate to 0.0000 mm was still turned away, because the official hole is 0.2 mm too small for its lead. A footprint that is taken over is copied into your project, not linked.

It redraws IC symbols. Where no official symbol exists, the symbol is drawn afresh from the pin data instead of repairing the source artwork: every pin on the 2.54 mm grid, one pin length, one text size, inputs left, outputs right, supply up, ground down. Twice the same input gives twice the same symbol.

It gives pins real electrical types. Types come from the taken-over official symbol first, then from name rules you can edit. Over the parts measured so far, 58 of 81 pin names are classifiable that way. A pin that cannot be classified is reported as not determined and left unspecified — never guessed, because a wrong power_in is worse than an honest blank.

It writes down what it did. Every field carries its origin, and the report names the fourteen KLC rules it checked with each result, plus seven more it does not yet check, each with the reason why not.

It merges multi-unit parts properly. A quad op-amp becomes one symbol with units U1A to U1D, not four parts. Shared pins land in unit 0.

It improves parts you already have. part2kicad refine re-runs the footprint match, the pin types and the rule check against a part that is already in your library, without making a single network request.

It never overwrites by accident. A part already in the library is reported, not replaced; --force is the only way past that.

Installation

pip install part2kicad

That is all it takes on any machine with Python 3.11 or newer. The package is a pure py3-none-any wheel, so nothing is compiled and no build toolchain is needed. If you use uv, uv pip install part2kicad does the same thing; uv tool install part2kicad or pipx install part2kicad keep it out of your project environment.

You also need KiCad 10.0 or newer. The tool calls kicad-cli, which ships with KiCad. On Windows that program is normally not on the search path, so part2kicad looks in the usual installation folders first. If it still cannot find it, say where it is:

set PART2KICAD_KICAD_CLI=C:\Program Files\KiCad\10.0\bin\kicad-cli.exe

In PowerShell the same line reads:

$env:PART2KICAD_KICAD_CLI = "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe"

To install from a wheel you build yourself, which is the route while working on the tool:

uv build
uv pip install dist/part2kicad-*.whl

Publishing to PyPI was a deliberate step of its own rather than a side effect of development. It cannot be taken back: it claims the name permanently and turns the command layout into a published interface that scripts and tutorials will anchor themselves to. A released version can be yanked, but its number can never be reused.

Your first part

  1. Open a terminal in your KiCad project folder — the one holding the .kicad_pro file. part2kicad finds the project the way git finds a repository: from the working directory upwards. If there is none, it stops instead of writing somewhere arbitrary.

  2. Take a part in. If you know the LCSC number:

    part2kicad add C93119
    

    If you do not, search by manufacturer part number or by description:

    part2kicad search lm393
    

    You get a numbered list with package, price, stock and whether CAD data exists at all. Pick a number and that part is taken straight in — search and import are one command.

  3. Open the schematic in KiCad and press A to place a symbol. The library is named after your project and is already registered; you do not have to add anything under Preferences → Manage Symbol Libraries.

  4. Check the 3D model. Open the board, press Alt+3. The model lives inside the project, so the folder still works on a machine that has never seen part2kicad.

If KiCad was already open while the part was written, use Preferences → Manage Symbol Libraries → OK or restart it. KiCad reads the library tables once, at start.

The report

--report prints the full report and files a copy next to the part, under <project>.reports/. It is Markdown, so it is still readable in a year without this tool installed. Here is the middle of the real one for the LM393 above — where the symbol came from, and what the rule check found, violations included:

## Where the symbol comes from (QUAL-04)

| Fact | Value |
| --- | --- |
| Way | taken over from the official KiCad library |
| Why | the official symbol name is the manufacturer part number with a suffix trimmed |
| Official library | Comparator |
| Official symbol | LM393 |
| Trimmed off the part number | M |
| Resolved from | LM2903 |
| KiCad version | 10.0.5 |

## Checked rules

| Rule | Subject | Demands | Result | Details |
| --- | --- | --- | --- | --- |
| KLC F5.1 (reference text) | footprint | the reference text of the footprint is 'REF**' | violated | found '', expected 'REF**' |
| KLC F5.2 (drawing on the fabrication layer) | footprint | at least one graphic lies on F.Fab or B.Fab | violated | no graphic lies on a fabrication layer; the 4 entries there are text only: fp_text (1x), property (3x) |
| KLC F5.3 (courtyard on the grid) | footprint | every courtyard coordinate is a multiple of the courtyard grid | violated | 4 of 4 courtyard coordinates are not multiples of 0.01 mm: -3.7499, -2.449, 2.449, 3.7499 |
| KLC S4.1 (pin grid) | symbol | every pin sits on the 2.54 mm grid | passed | — |
| KLC S4.4 (pin types) | symbol | not every pin carries the electrical type 'unspecified' | passed | — |

The full report has seven sections: the facts about the part, where the symbol came from, which footprint it got and why, the pin types with the source of each one, the origin of every single field, the rules that were checked, and the rules that were deliberately left out with the reason for each. Every judgement carries its figures — "0.2498 mm off, and 0.20 mm is what is allowed", not "close enough".

--json gives the same content as a machine-readable structure, out of the same source. There is no second, parallel truth.

Everyday use

part2kicad add C2040                 # take a part in by number
part2kicad search rp2040             # search, pick, take it in — one command
part2kicad add C2040 --report        # print the full report and file it beside the part
part2kicad add C2040 --force         # replace a part that is already there
part2kicad add C2040 --symbol redraw # force one of the four symbol routes
part2kicad add C2040 --project ../my-board   # name the project explicitly
part2kicad add C2040 --json          # machine-readable output, asks nothing
part2kicad add C2040 --verbose       # one line per fetch on stderr
part2kicad refine C93119             # improve a part already in the library
part2kicad refine --all              # go over the whole project library

Choosing how the symbol is made

--symbol takes auto, redraw, repair or keep. auto is the default and decides for itself: take over the official symbol where there is one, otherwise draw the symbol afresh from the pin data, otherwise repair the source drawing. The other three force one route. Whichever way it goes, the report names the route and the reason — including, when it falls back, why the preferred route was not available.

Refining what you already have

part2kicad refine works on a part that is already in your project library and makes no network request at all — that is not a promise in prose, it is a bolt in the test suite that fails the build if a fetch ever appears on that path. It re-runs the footprint match, the pin types and the rule check against the files on disk.

Like add, it reports before it writes:

refine my-board.kicad_sym
  0 would change · 1 unchanged · 0 skipped · 0 failed
  LM393M (C93119) unchanged
  ! Price and stock are neither added nor changed by refine: both would need exactly the
    fetch this command avoids.

--force performs the change. --all walks the whole project library; it can be interrupted, a single failing part does not stop the run, and symbols without a Source field — anything you drew yourself — are left alone and named as left alone.

Taking the same part in twice

If the part is already in the project library, part2kicad says so along with the date of the first fetch and writes nothing. Anyone who has touched up a part by hand does not lose that work to a careless second command.

--force replaces it. A symbol already placed in the schematic then has to be brought up to date there, via Tools → Update Symbols from Library.

What ends up on the part

Group Fields
Provenance Supplier Part, Manufacturer, Manufacturer Part, Datasheet, Source, Fetch Date
Commercial data Price and Stock, each with the date it was fetched
Technical parameters whatever the source delivers, under its unchanged field names
Assembly JLCPCB Part Class (Basic/Extended) — it decides the assembly cost

Every field except Reference and Value is created hidden, so the schematic stays readable. Price and stock only come with part2kicad search; a fetch by part number does not carry them, and part2kicad does not invent a price.

The Datasheet link is checked before it is written: one HEAD request asks the server what it would actually deliver. Many links that end in .pdf return a web page, and the field says so rather than pretending. Where an official KiCad symbol was taken over, its datasheet link wins and the source link is kept beside it as Source Datasheet.

When something goes wrong

What you see What it means What to do
kicad-cli not found KiCad is not installed, or not where the tool looked Set PART2KICAD_KICAD_CLI to the full path, see Installation
no KiCad project found You are not inside a project folder cd into the folder holding the .kicad_pro file, or pass --project
this part has no CAD data The supplier has the part but no symbol or footprint for it The message names the part and links its datasheet; draw it by hand or pick another part
already in the library The part was taken in before That is the safeguard, not an error. --force replaces it
The library does not show in KiCad KiCad read its library tables at start Preferences → Manage Symbol Libraries → OK, or restart KiCad
Everything hangs for two minutes The supplier is throttling you Leave it running; it waits and retries. Ctrl-C stops it cleanly at any time

What it cannot do yet

The list stays here, and it stays complete, because a tool whose whole point is honest reporting cannot be coy about itself:

  • A local result store does not exist yet, so a second add … --force fetches the same geometry again. It arrives with phase 5, together with offline search and filtering by value and price.
  • refine does not take over an official symbol. On an existing part it keeps the symbol it finds and improves footprint, pin types and report around it. That is deliberate — an earlier version redrew a taken-over symbol and threw the good one away — but it means the official-symbol route is available on import only.
  • refine says nothing about a footprint candidate it rejected. The import report names the candidate and the deviation in figures; the refine report only lists changes, so a rejection leaves no line at all.
  • The field names of the technical parameters stay as the source delivers them — so, inconsistent. Unifying them is a step of its own and has not been taken.
  • The symbol naming scheme and the target library name are not configurable. Everything else about the drawing and matching lives in recipe.toml; these two are still hard-wired to the part number and the project name.
  • macOS is untested, and nobody has run this on Linux yet. Development and testing happen on Windows. For Linux the platform assumptions are pinned down statically — no hard-wired path, no shell invocation, no file access without a stated encoding, configuration folder from platformdirs — but a run is still outstanding.
  • Two concurrent invocations on the same library can lose a symbol. The swap of the finished file is atomic; the read-modify-write before it is not. For an interactive single-workstation tool, a file lock has deliberately not been built in.
  • Price and stock are only available via part2kicad search, see above.

How this tool treats the data sources

part2kicad queries foreign servers that have no contract with us to serve it. What it does while doing so is written out here in full, because a user is entitled to know what runs in their name.

Endpoints used

All the addresses live in src/part2kicad/recipe.toml and not in the program code. If the counterpart changes, the repair is an edit there — not a program update.

Purpose Address When
Search https://pro.easyeda.com/api/eda/product/search once per search command
Geometry (symbol and footprint) https://easyeda.com/api/products/{lcsc}/components once per part taken in
3D model (STEP) https://modules.easyeda.com/…/{uuid} once per part taken in, if one is on file
Datasheet check whichever address the response names — measured, atta., item. and so.szlcsc.com one HEAD request per part taken in

Symbol and footprint come from one fetch; there is no second one for the footprint. The datasheet check is a HEAD request: it asks what the server would deliver and reads no body. If a part is already in the library, no fetch happens at all without --force. And part2kicad refine touches none of these addresses — it is the one command that is guaranteed to stay silent on the wire.

Identification

part2kicad identifies itself as

part2kicad/<version> (+https://pypi.org/project/part2kicad/)

An honest identification that names the product. Explicitly not: a faked browser user agent, or bending name resolution to get around a block. This is not decoration — measured, the honest route gets through, and the dishonest one would not be acceptable even if it were necessary.

The identification can be changed without touching the program: your own recipe.toml in the platform's configuration folder (Windows %LOCALAPPDATA%\part2kicad\, Linux ~/.config/part2kicad/) overrides individual values selectively:

[identity]
user_agent = "my-identification/1.0 (+https://example.example)"

Minimum intervals and behaviour when blocked

Every endpoint has its own time budget — the block we measured is tied to the path, and a shared budget would slow the search down as soon as a geometry fetch is due.

Endpoint Minimum interval Maximum attempts
Search 2.5 s 3
Geometry 3.0 s 3
3D model 1.0 s 3
Datasheet check 1.0 s 3

The counterpart starts blocking after roughly 45 fetches within a few minutes — cumulatively, not by peak rate. It then answers with a bare HTTP 403, without Retry-After and without HTTP 429; the block therefore cannot be predicted, only recognised. It clears by itself after about two minutes.

In that case part2kicad waits, starting at 120 seconds and doubling per attempt, for at most three attempts — 120 + 240 = six minutes in total. More would be out of proportion: measured, the block clears after around two minutes, and if it is still there after three times that, it is not the ordinary rate limit; waiting longer is then no better a bet than telling the user. The wait is shown as a status line — two minutes of silence could not be told apart from a crash — and Ctrl-C ends it at any time with a message instead of a stack trace. If the counterpart still will not let up, the command stops with a message saying that it is not your machine's fault. Nothing is written along the way: as long as not all the pieces are together, the library stays untouched.

The numbers all live in recipe.toml and can be changed in your own user file — a limit hard-coded in the program would take that option away.

The counterpart's exclusion list

easyeda.com/robots.txt disallows //api/ paths — and with them the geometry endpoint. That is named openly here rather than passed over:

  • The route is used deliberately, because there is no other one that would yield a part's CAD data.
  • It is minimised: one fetch per part, never a full catalogue, none at all for a part that is already present, and none at all for part2kicad refine.
  • A local cache that would also spare the repeated fetch of the same part is still missing — it arrives with phase 5. So a second part2kicad add C2040 --force fetches the geometry a second time. This is stated here because a disclosure that lists a measure not yet taken is not a disclosure.
  • The search traffic — that is, the volume — goes to pro.easyeda.com, whose own exclusion list names only /login and a set of named SEO bots, not /api/.

Anyone who judges this differently can leave part2kicad add alone and use the tool for searching only.

Development

git clone https://github.com/AltF4Quit/part2kicad
uv sync
Run Command
Fast lane, without KiCad pytest -m "not kicad and not live"
Full run (default) pytest -m "not live"
Live tests against the real counterpart pytest -m live --live

Live tests never run by accident: they need both the marker and the --live switch. Tests that need an installed KiCad skip themselves with a visible reason when none is found.

License

GPL-3.0-or-later, see LICENSE.

Metadata

Release files for part2kicad 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for part2kicad 0.4.0
File Size Uploaded
part2kicad-0.4.0.tar.gz 590.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for part2kicad 0.4.0
File Interpreter ABI Platform
part2kicad-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 813.3 kB

Release files / part2kicad-0.4.0.tar.gz

Download URL part2kicad-0.4.0.tar.gz
Size 590.9 kB
Tags Source
SHA-256 checksum
How to use checksums
752eee10f561f1b65ce817d6c8b106b9f0d7217ebbe0d18ec13f82e92c592d12
BLAKE2b-256 checksum
How to use checksums
4eeccdb59fa5086b8c6a21b09611b531379c45aaf6d618d4e8d1c31800604722
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / part2kicad-0.4.0-py3-none-any.whl

Download URL part2kicad-0.4.0-py3-none-any.whl
Size 222.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
efe3d178673100c29e62c3e6e9c60f35e4e2fcfa002745a4dcf24cde320dfd2e
BLAKE2b-256 checksum
How to use checksums
e499a47a12d8a46d90fcbcfbe044a429b959c87c45be09e0cebdd1a8e6fc5011
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page