Using crates.io
crates.io is the official package registry for Rust. It hosts over 140,000
published crates — libraries and tools that the Rust community has written and shared.
Cargo, Rust's build tool, integrates with crates.io directly, so adding a dependency
is a matter of editing one line in Cargo.toml.
This page covers everything you need to find, add, manage, and eventually publish crates.
Adding Dependencies
Open your project's Cargo.toml and add the crate name and version under the
[dependencies] section:
[dependencies]
serde = { version = "1", features = ["derive"] }
rand = "0.8"
anyhow = "1"Run cargo build (or any cargo command) and Cargo will download and compile the
new dependencies automatically. The first build fetches the source; subsequent builds
use a local cache.
From Rust 1.62 you can also use the cargo add subcommand to add and resolve a
dependency from the command line:
# Add the latest compatible version cargo add serde # Add with features cargo add serde --features derive # Add a specific version cargo add rand@0.8
Updating crates.io index
Adding serde v1.0.203 to dependencies
Features:
+ derive
+ std
- alloc
...Semantic Versioning
Rust crates follow Semantic Versioning (SemVer): MAJOR.MINOR.PATCH.
- PATCH bump — backwards-compatible bug fixes
- MINOR bump — backwards-compatible new features
- MAJOR bump — breaking changes
Cargo version specifiers:
Specifier | Meaning | Example range |
|---|---|---|
^1.2.3 (default) | Compatible with 1.2.3 — any 1.x.y where x>=2 or y>=3 | =1.2.3, <2.0.0 |
^0.2.3 | Pre-1.0 compatibility — any 0.2.x | =0.2.3, <0.3.0 |
~1.2.3 | Patch-level only | =1.2.3, <1.3.0 |
=1.2.3 | Exact version | 1.2.3 only |
=1.2, <1.5 | Range | 1.2.0 to 1.4.x |
Any version (avoid in libraries) | No constraint |
^0.2allows any 0.2.x but not 0.3.0, because breaking changes may occur in minor version bumps before a stable 1.0 is released.Cargo.lock and Reproducible Builds
When Cargo resolves dependencies it writes the exact versions it chose to
Cargo.lock. On subsequent builds Cargo reads the lock file instead of
re-resolving — this guarantees reproducible builds.
Convention:
- Application (binary crate): commit
Cargo.lockto version control. - Library crate: do not commit
Cargo.lock— let downstream users resolve.
# Update all dependencies to the latest versions within your constraints cargo update # Update only a specific crate cargo update --precise 0.8.5 rand
Inspecting the Dependency Tree
# Print the full dependency tree cargo tree # Show only dependencies that include a specific crate cargo tree --invert rand # Show duplicated crate versions (a common source of binary bloat) cargo tree --duplicates
my-project v0.1.0
├── anyhow v1.0.86
├── rand v0.8.5
│ ├── rand_chacha v0.3.1
│ │ ├── ppv-lite86 v0.2.17
│ │ └── rand_core v0.6.4
│ └── rand_core v0.6.4
└── serde v1.0.203
└── serde_derive v1.0.203 (proc-macro)Auditing for Security Vulnerabilities
# Install the audit tool once cargo install cargo-audit # Check your dependency tree against the RustSec advisory database cargo audit
Fetching advisory database from https://github.com/RustSec/advisory-db.git
Loaded 737 security advisories (from ~/.cargo/advisory-db)
Scanning Cargo.lock for vulnerabilities (133 crate dependencies)
No vulnerable packages foundcargo audit to your CI pipeline so that newly discovered vulnerabilities in your dependencies are caught automatically before they reach production.Dev and Build Dependencies
Not all dependencies are needed at runtime. Cargo supports two additional dependency sections:
[dependencies]
serde = { version = "1", features = ["derive"] }
[dev-dependencies]
# Only compiled for tests and benchmarks — not included in release binaries
criterion = "0.5"
proptest = "1"
[build-dependencies]
# Only used in build.rs scripts — not included in the final binary
bindgen = "0.69"
cc = "1"Feature Flags
Many crates expose features — optional capabilities that you opt into. This keeps
the default build lean and compile times fast. You activate features in
Cargo.toml:
[dependencies]
# Activate only the features you actually need
tokio = { version = "1", features = ["rt-multi-thread", "macros", "io-util"] }
serde = { version = "1", features = ["derive"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false }Use default-features = false to opt out of a crate's default feature set and only
enable what you need — useful for embedded or WASM targets that cannot use
std-dependent features.
Finding Good Crates
crates.io (crates.io) — the official registry. Search by keyword; shows download counts and recent activity.
docs.rs (docs.rs) — auto-generated API documentation for every published crate. The canonical place to read a crate's API.
lib.rs (lib.rs) — a curated, searchable alternative front-end for crates.io with better category browsing.
blessed.rs (blessed.rs) — a community-maintained guide to the "blessed" (recommended) crates for common tasks.
are we X yet sites — e.g. arewewebyet.org, arewegameyet.com — show the ecosystem maturity for specific domains.
Must-Know Crates
Crate | Purpose |
|---|---|
serde + serde_json | Serialisation and deserialisation — de facto standard |
tokio | Async runtime — the most widely used async executor |
reqwest | HTTP client built on tokio |
anyhow | Ergonomic error handling for applications |
thiserror | Derive macros for custom Error types in libraries |
clap | Command-line argument parsing |
rayon | Data-parallel iterators for CPU-bound workloads |
chrono | Date and time handling |
uuid | UUID generation and parsing |
rand | Random number generation |
tracing | Structured, async-aware logging and instrumentation |
sqlx | Async SQL with compile-time checked queries |
Publishing a Crate
Create an account on crates.io and generate an API token under Account Settings.
Authenticate locally:
cargo login <your-token>Fill in the required fields in
Cargo.toml:name,version,edition,description,license, andrepository.Ensure your crate builds cleanly:
cargo build && cargo testDo a dry run to catch issues before uploading:
cargo publish --dry-runPublish:
cargo publishDocumentation is automatically generated and published to docs.rs within minutes.
# Minimum required Cargo.toml fields for publishing [package] name = "my-awesome-crate" version = "0.1.0" edition = "2021" description = "A short description of what this crate does" license = "MIT OR Apache-2.0" repository = "https://github.com/yourname/my-awesome-crate" readme = "README.md" keywords = ["example", "tutorial"] categories = ["development-tools"]
Yanking a Version
If you publish a version with a serious bug or a security vulnerability, you can
yank it. Yanking marks a version as "do not use for new projects" without removing
it — existing users who already have that version in their Cargo.lock are
unaffected, but new cargo add and cargo update commands will skip the yanked
version.
# Yank a specific version cargo yank --version 0.1.0 my-awesome-crate # Un-yank if you made a mistake cargo yank --undo --version 0.1.0 my-awesome-crate
cargo audit, and docs.rs combine to make adding, updating, and trusting third-party code straightforward.