Skip to content
RFrftools.io
ToolsMarch 11, 20266 min read

Automate RF Calculations in Python with rftools

The rftools Python package gives you programmatic access to 203 RF and electronics calculators from rftools.io — with a typed API, CLI, batch mode, and async support.

Contents

Why Automate RF Calculations?

Running a single VSWR calculation by hand is fine. But when you're doing a parameter sweep across 50 distances, comparing link budgets for 12 antenna configurations, or writing a Jupyter notebook for a design review, clicking through a web UI isn't the answer.

The rftools Python package gives you the full rftools.io calculator engine in your Python environment — no web scraping, no copy-pasting — just clean, typed function calls.

Installation

pip install rftools-io

A free API key is required — get one at rftools.io/pricing (5 calls/month free). For automated workflows, the API tier gives you 10,000 calls/month.

Your First Calculation

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.333

rftools.calculate() returns a CalculatorResult — dict-like, so you can access outputs by key.

Typed Stubs for IDE Autocomplete

For better discoverability and IDE completion, use the typed category modules:

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=100.0) print(f'FSPL: {fspl["pathLoss"]:.1f} dB') # 80.0 dB

dipole = antenna.dipole_antenna(frequency=433.0) print(f'Dipole length: {dipole["length"]:.0f} mm')

All 13 categories are available: rf, pcb, power, signal, antenna, general, motor, protocol, emc, thermal, sensor, unit_conversion, audio.

Batch Mode (API Tier)

The batch API runs up to 50 calculations in a single HTTP request — ideal for sweeps:

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}) for d in distances ])

for d, r in zip(distances, results): if r.ok: print(f'{d:>6}m → {r.values["pathLoss"]:.1f} dB')

Output:

10m  →  60.0 dB     50m  →  74.0 dB    100m  →  80.0 dB    500m  →  94.0 dB   1000m  →  100.0 dB

Async Support

For FastAPI services or async Jupyter kernels, use AsyncClient:

import asyncio
import rftools

async def main(): async with rftools.AsyncClient(api_key='rfc_live_xxx') as client: result = await client.calculate('rf-link-budget', { 'txPower': 20, 'txGain': 6, 'rxGain': 3, 'frequency': 2400, 'distance': 500, }) print(f'Received power: {result["rxPower"]:.1f} dBm')

asyncio.run(main())

CLI

The rftools command runs calculations from the terminal:

# Single calculation
rftools calc vswr-return-loss --vswr 2.5

# JSON output — pipe to jq rftools calc vswr-return-loss --vswr 2.5 --json | jq '.values.returnLoss'

# List available calculators rftools list --category rf

# Show a calculator's inputs and outputs rftools info free-space-path-loss

The CLI is useful for quick checks in terminal workflows or shell scripts.

Error Handling

All errors raise typed exceptions:

from rftools.exceptions import AuthError, RateLimitError, ValidationError

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 ValidationError as e: print(f'Bad inputs: {e.detail}')

Browsing the Calculator Catalog

# All 203 calculators
calcs = rftools.list_calculators()
print(f'{len(calcs)} calculators available')

# Filter by category rf_calcs = rftools.list_calculators(category='rf') for c in rf_calcs: print(f'{c.slug}: {c.title}')

# Inspect a specific calculator's inputs and outputs info = rftools.get_calculator('noise-figure-cascade') for field in info.inputs: print(f' in: {field.id} ({field.unit})') for field in info.outputs: print(f' out: {field.id} ({field.unit})')

Here's how to build a receive-power-vs-distance chart in a Jupyter notebook:

import numpy as np
import matplotlib.pyplot as plt
from rftools.calculators import rf

distances = np.logspace(1, 4, 40) # 10m to 10km rx_powers = []

for d in distances: r = rf.rf_link_budget( txPower=30, # dBm txGain=6, # dBi rxGain=6, # dBi frequency=915, # MHz distance=float(d), ) rx_powers.append(r['rxPower'])

plt.semilogx(distances, rx_powers) plt.axhline(-100, color='r', linestyle='--', label='Sensitivity (-100 dBm)') plt.xlabel('Distance (m)') plt.ylabel('Received Power (dBm)') plt.title('915 MHz Link Budget') plt.legend() plt.grid(True) plt.show()

Getting Started

Install with pip install rftools-io. Source and issues: github.com/rftools/rftools-py. API keys and pricing at rftools.io/pricing.

Related Articles