rftools Python Library
Programmatic access to all 255 RF & electronics calculators — typed functions, batch mode, async support, and a CLI. Free tier requires no API key.
pip install rftools-io
Python 3.9+. Dependencies: httpx, pydantic, click. View on PyPI
Quick Start (free tier)
Requires an API key. Free tier: 5 calls/month — get one free at rftools.io/pricing.
import rftools
result = rftools.calculate('vswr-return-loss', {'vswr': 2.5})
print(f'Return Loss: {result["returnLoss"]:.2f} dB') # 9.54 dB
print(f'Reflection Coeff: {result["reflectionCoeff"]:.3f}') # 0.333rftools.calculate() returns a dict-like CalculatorResult. Access outputs by key.
Typed Category Stubs
IDE-friendly typed functions with parameter names and defaults that match the rftools.io web UI. All 13 categories available.
from rftools.calculators import rf, antenna, pcb
# Parameter names and defaults match the rftools.io web UI
fspl = rf.free_space_path_loss(frequency=2400.0, distance=0.1) # MHz, km
print(f'FSPL: {fspl["fspl_dB"]:.1f} dB') # 80.1 dB
dipole = antenna.dipole_antenna(frequency=433.0)
print(f'Dipole length: {dipole["length"]:.0f} mm')
result = pcb.trace_width_current(current=2.0, tempRise=10.0, copperWeight=1.0)Batch API
Run up to 50 calculations in a single HTTP request — ideal for parameter sweeps. Requires an API-tier key (10,000 calls/month). Get a key.
import rftools
client = rftools.Client(api_key='rfc_live_xxx')
# or: export RFTOOLS_API_KEY=rfc_live_xxx
distances = [10, 50, 100, 500, 1000]
results = client.batch([
('free-space-path-loss', {'frequency': 2400, 'distance': d / 1000}) # km
for d in distances
])
for d, r in zip(distances, results):
if r.ok:
print(f'{d:>6} m → {r.values["fspl_dB"]:.1f} dB')Solve for a Target
client.solve() finds the value of one input that brings an output to a target — the trace width that gives 50 Ω — and returns it with the forward result at exactly that value, computed by POST /api/py/v1/calculate/solve. One metered call. Available from rftools-io 0.4.0.
import rftools
client = rftools.Client(api_key='rfc_live_xxx')
# The trace width that reaches 50 Ω on 1.51 mm FR-4, rounded to a 0.001 mm grid
result = client.solve(
'microstrip-impedance',
{'substrateHeight': 1.51, 'dielectricConstant': 4.5, 'copperThickness': 35},
'traceWidth', 'impedance', 50,
grid=0.001,
)
print(f'{result.value:.3f} mm') # 2.781 mm
print(result.reached, result.evaluations) # True 68
print(f'{result.result.values["impedance"]:.2f} Ω') # 50.00 Ω
print(result.result.provenance.formula_ref) # Hammerstad & Jensen (1980); ...Client.solve(slug, inputs, solve_for, target_output, target_value, grid=None, range=None) returns a SolveResult with .value, .unrounded, .reached, .evaluations, .warnings and .result — the same CalculatorResult client.calculate() returns, provenance included, for the inputs with solve_for set to .value. A target the search cannot reach still returns normally, with .reached is False and the nearest value found, and still costs one call. See /docs/api for the request and response fields, the search range and the refusals.
Async Support
Use AsyncClient for FastAPI services, async Jupyter kernels, or concurrent sweeps.
import asyncio
import rftools
async def main():
async with rftools.AsyncClient(api_key='rfc_live_xxx') as client:
result = await client.calculate('vswr-return-loss', {'vswr': 2.5})
print(result['returnLoss'])
asyncio.run(main())CLI
The rftools command is installed automatically with the package.
rftools calc vswr-return-loss --vswr 2.5
rftools calc vswr-return-loss --vswr 2.5 --json | jq .values
rftools list --category rf
rftools info free-space-path-loss
rftools solve microstrip-impedance --for traceWidth --target impedance=50 --grid 0.001 --param substrateHeight=1.51 --param dielectricConstant=4.5 --param copperThickness=35
rftools version
Error Handling
from rftools.exceptions import AuthError, RateLimitError, ValidationError, NotFoundError
try:
result = client.calculate('vswr-return-loss', {'vswr': 2.5})
except RateLimitError as e:
print(f'Quota exceeded. Retry after {e.retry_after}s')
except AuthError:
print('Invalid API key')
except NotFoundError:
print('Unknown calculator slug')
except ValidationError as e:
print(f'Bad inputs: {e.detail}')| Exception | When |
|---|---|
AuthError | Invalid or missing API key |
RateLimitError | Monthly quota exceeded (has .retry_after attribute) |
ValidationError | Bad inputs (HTTP 422) — has .detail attribute |
NotFoundError | Unknown calculator slug |
APIError | Unexpected HTTP error — has .status_code attribute |
All 13 Categories
Import from rftools.calculators.
| Module | Count |
|---|---|
rf | 36 |
pcb | 36 |
power | 23 |
signal | 14 |
antenna | 11 |
general | 24 |
motor | 22 |
protocol | 11 |
emc | 16 |
thermal | 6 |
sensor | 17 |
unit_conversion | 19 |
audio | 18 |
iot | 2 |
API Key
Set RFTOOLS_API_KEY to avoid passing it explicitly. The module-level helpers and Client() both read it automatically.
export RFTOOLS_API_KEY=rfc_live_xxx
Get a key at /pricing. API tier: $19/mo, 10,000 calls/month.
Ready to automate?
Install the library, get a free API key, and run your first calculation in under a minute.
Or get a free API key (5 calls/month) — no credit card required.