/free.llms.txt
Free & Public RPCs
No config file, no API keys, no provider signup. Start eRPC and it immediately routes every EVM chain through two auto-injected providers — a curated public endpoint catalog and Envio HyperRPC — backed by eRPC's full resilience stack. The fastest way to go from zero to any chain in development or prototyping.
Quick taste
Illustrative — this is the default behavior with no config:
npx start-erpcOr deploy instantly to Railway:
Then query any chain by its EVM chain ID:
curl 'http://localhost:4000/main/evm/42161' \
--header 'Content-Type: application/json' \
--data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'Free & Public RPCs — full agent referenceExpand for every option, default, and edge case — or copy this entire section into your AI assistant.
How it works
When a project has zero providers, zero upstreams, and no CLI --endpoint flags, eRPC
logs a warning and auto-injects two providers before any request is processed:
repository(idpublic) — fetcheshttps://evm-public-endpoints.erpc.cloudon first request for a chain and re-checks every hour. The catalog is a JSON map of{ "<chainId>": { "endpoints": [...] } }. Eachhttp/httpsentry becomes a separate upstream withautoIgnoreUnsupportedMethods: true;wss/wsentries are silently skipped. Upstream ids embed a redacted endpoint (https#redacted=ab12c) so no raw URLs appear in logs or metrics.envio— HyperRPC atrpc.hypersync.xyz. A 14-method read-only allow-list is injected (eth_chainId,eth_blockNumber,eth_getBlockByNumber,eth_getBlockByHash,eth_getTransactionByHash,eth_getTransactionByBlockHashAndIndex,eth_getTransactionByBlockNumberAndIndex,eth_getTransactionReceipt,eth_getBlockReceipts,eth_getLogs,eth_getFilterLogs,eth_getFilterChanges,eth_uninstallFilter,eth_newFilter). Write methods fall through torepositoryupstreams only.
On the first request for a chain, eRPC schedules bootstrap tasks for both providers and waits up to 30 seconds (capped by the request deadline) polling every 200 ms until at least one upstream is ready. Subsequent requests on the same chain reuse the prepared upstreams. Failed bootstrap tasks are auto-retried with exponential backoff (factor 1.5, 3 s → 130 s).
The hot-path data path is lock-free: both providers cache catalog data in a RemoteDataCache
backed by an atomic.Pointer, so reads on warm chains involve no I/O and no mutex.
Config schema
Auto-injected providers are not configurable through YAML. To understand their exact defaults:
| Field | Type | Auto-injected value | Behavior / footguns |
|---|---|---|---|
providers[].id | string | "public" (repository), "envio" (envio) | Appears in upstream task names and metric labels. Do not reuse "public" if you later add explicit providers — id collisions cause undefined upstream selection behavior. |
providers[].vendor | string | "repository" / "envio" | Selects the vendor integration. |
providers[].settings | map | {} (all vendor defaults) | Cannot be customized without opting out of auto-injection by explicitly adding a provider or upstream. |
repository › repositoryUrl | string | "https://evm-public-endpoints.erpc.cloud" | Remote JSON catalog. Non-integer chain id keys are silently skipped. Only http/https entries produce upstreams. |
repository › recheckInterval | duration | 1h | Catalog freshness window. YAML footgun: the value is read with a Go .(time.Duration) type assertion; YAML decodes scalars to string/int64, so the assertion always fails silently and the 1 h default is used regardless of what you write. Only Go programmatic config (common.VendorSettings{"recheckInterval": 1*time.Hour}) can override it. |
repository › autoIgnoreUnsupportedMethods | bool | true | Public RPCs vary wildly in method support; unsupported-method errors are treated as permanent and that method is skipped on that upstream. |
envio › rootDomain | string | "rpc.hypersync.xyz" | URL template https://{chainId}.{rootDomain}. |
envio › apiKey | string | "" (omitted from URL) | Appended as a path segment when non-empty. |
envio method allow-list | injected | ignoreMethods: ["*"] + 14 explicit allowMethods | Listed under "How it works". Any method not in the list is blocked and falls through to repository upstreams. |
Worked examples
1. Prototyping on Arbitrum with no setup. No config needed — just start and query:
npx start-erpc
# then
curl 'http://localhost:4000/main/evm/42161' \
-d '{"method":"eth_getLogs","params":[{"fromBlock":"latest"}],"id":1,"jsonrpc":"2.0"}'When using a human-readable alias in a project config, the URL shortens:
projects:
- id: main
networks:
- id: evm:42161
alias: arbitrum
# then: curl http://localhost:4000/main/arbitrum2. Switching to explicit providers once you have an API key. Auto-injection turns off the moment any provider or upstream is present. To graduate from zero-config:
projects:
- id: main
providers:
- id: alchemy
vendor: alchemy
settings:
apiKey: ${ALCHEMY_KEY}This disables both repository and envio auto-injection entirely.
3. Pointing repository at a private mirror (Go programmatic config only). Because
recheckInterval and repositoryUrl cannot be overridden from YAML, the only path that
works is Go config:
providers: []common.ProviderConfig{{
Id: "custom-repo",
Vendor: "repository",
Settings: common.VendorSettings{
"repositoryUrl": "https://my-internal-catalog.example.com",
"recheckInterval": 30 * time.Minute,
},
}}This is an explicit provider (not auto-injected) so envio is no longer auto-added.
4. Read-only chain fan-out behind Envio. Because envio covers 14 read methods with
sub-millisecond latency for 61 well-known chains, a workload heavy on eth_getLogs or
eth_getBlockReceipts benefits from the zero-config default even in staging environments
where you already have API keys — add Envio as an explicit upstream alongside your provider:
upstreams:
- id: envio-hyper
endpoint: envio://rpc.hypersync.xyzRequest/response behavior
- URL path format:
POST /<project>/<architecture>/<chainId>— e.g./main/evm/42161. A human-readable network alias (alias: arbitruminnetworks[]) makes the path/main/arbitrum. See URL structure for all accepted shapes. - Only
POSTandOPTIONSreach the proxy; any other method (GET, etc.) is silently treated as a healthcheck and returns a JSON health envelope, not a JSON-RPC response. - Write methods (
eth_sendRawTransaction, etc.) are not blocked by eRPC — but they cannot route through theenvioprovider (14-method allow-list). Ifrepositoryupstreams for the chain are available they will carry the write. - Responses carry standard
X-ERPC-*headers (attempts, upstream, etc.) even on zero-config setups. - Unknown chain IDs return HTTP 404 with a JSON-RPC error body (
ErrNetworkNotSupported) after all provider tasks complete without producing any upstream for that chain.
Best practices
- Use zero-config only for development and prototyping. Public endpoints have no SLA, unpredictable rate limits, and no authentication — not suitable for production traffic.
- Graduate to explicit providers before going live. Adding a single
providers[]entry disables auto-injection and gives you full resilience control. See Providers. - Add auth and rate limits when exposing eRPC externally. Zero-config has no per-project auth, no rate limiter, and no circuit-breaker budget configured on auto-injected upstreams. See Auth and Rate limiters.
- Expect cold-start latency on first request per chain.
repositoryhas no static fallback — the first request for a new chain may wait for the HTTP catalog fetch (retried with 3 s → 130 s backoff). Warm the chain before serving user traffic. - Do not reuse provider id
"public"in explicit configs. It is reserved by the auto-injected repository provider; a collision causes upstream-id overlap. recheckIntervalonly works from Go programmatic config. YAML silently ignores the value; the 1 h default always applies in YAML/TS setups.- Monitor
erpc_upstream_request_total{vendor="repository"}to spot slow public endpoints. Theupstreamlabel carries the redacted endpoint id for drill-down without leaking URLs.
Edge cases & gotchas
- Explicit
providers: []in YAML still triggers auto-injection ifupstreamsis also empty and no CLI--endpointflags were passed. There is no YAML opt-out flag; you must add at least one explicit provider or upstream to disable it. Source:common/defaults.go:L1113-1115 recheckIntervalfrom YAML is always silently ignored —VendorSettingsis amap[string]interface{}; YAML decodes duration strings/integers tostring/int64, nottime.Duration, so the.(time.Duration)type assertion fails and the vendor default is used. Only Go programmatic config can override it. Source:thirdparty/repository.go:L56-59repositorycatalog cold start is not instant — first request for any chain may wait for the HTTP fetch (no static fallback).enviocold start is fast for 61 known chains but requires a liveeth_chainIdprobe for unknown ones (10 s timeout). Source:thirdparty/repository.go:L61-64;thirdparty/envio.go:L22-84envioTLS error on unknown subdomain = unsupported — Envio's k8s load-balancer returns a bad certificate for unrecognized chain subdomains; eRPC treats"failed to verify certificate"as(false, nil)(chain not supported), not an error. Source:thirdparty/envio.go:L139-141wss/wsendpoints in the repository catalog are silently skipped — onlyhttp/httpsentries produce upstreams. Source:thirdparty/repository.go:L121-166- Write methods are unavailable via envio — the 14-method allow-list blocks
eth_sendRawTransactionand all state-mutation calls. Writes fall through torepositoryupstreams only; if no repository upstream supports the method it will fail. - Rate limits on public endpoints are uncontrolled — no rate-limit budget or per-upstream circuit-breaker is configured on auto-injected upstreams. A misbehaving upstream will only be flagged once the upstream's circuit-breaker window fills (if a project-wide policy is configured).
- Provider id
"public"is reserved by the auto-injected repository provider. Adding an explicit provider with the same id causes upstream-id collisions; the upstream registry will deduplicate by id, silently merging them. Source:common/defaults.go:L1126-1133 envionil Evm dereference in GenerateConfigs —GenerateConfigsdereferencesupstream.Evmwithout a nil check (envio.go:202). In practice the provider bootstrap always setsEvmforevm:networks, but a manually-constructed upstream withoutEvmwould panic here. Source:thirdparty/envio.go:L202
Observability
| Metric | Type | Labels | When it fires |
|---|---|---|---|
erpc_upstream_request_total | counter | project, vendor, network, upstream, ... | Every request forwarded to a repository or envio upstream. vendor label is "repository" or "envio". |
erpc_upstream_request_duration_seconds | histogram | project, vendor, network, upstream | Latency of each upstream call; useful for spotting slow public endpoints. |
erpc_selection_score | gauge | project, network, method, upstream | Per-upstream score produced by the selection policy (sortByScore). Lower = better. |
Notable log messages:
warn: no providers or upstreams found in project; will use default 'public' endpoints repository— fires at project setup when auto-injection triggers.debug: provider does not support network; skipping upstream creation— fires when a chain is not in the catalog.warn: vendor remote-data refresh failed; keeping previous snapshot— catalog fetch failed; previous data used.
Source code entry points
common/defaults.go:L1113-L1142(opens in a new tab) — auto-injection conditions and injected provider construction (len(providers)==0 && len(upstreams)==0 && no CLI endpoints)thirdparty/repository.go:L41-L92(opens in a new tab) —SupportsNetwork,autoIgnoreUnsupportedMethodsdefault, cold-start guard (ErrRemoteCacheCold)thirdparty/repository.go:L121-L166(opens in a new tab) —GenerateConfigsfan-out: one upstream perhttp/httpsendpoint, redacted idsthirdparty/envio.go:L22-L167(opens in a new tab) — 61-chain fast path + liveeth_chainIdprobe for unknown chains; TLS-error-as-unsupported branchthirdparty/envio.go:L174-L194(opens in a new tab) — 14-method allow-list injectionthirdparty/remote_cache.go:L13-L78(opens in a new tab) —RemoteDataCachedesign rationale: lock-free hot path, single-flight async refresh, copy-on-writeupstream/registry.go:L155-L293(opens in a new tab) — lazy provider bootstrap, 30 s readiness wait,ErrNetworkInitializing/ErrNetworkNotSupportedutil/initializer.go:L179-L182(opens in a new tab) — exponential retry parameters for failed bootstrap tasks (factor 1.5, 3 s → 130 s)util/redact.go:L10-L36(opens in a new tab) — endpoint redaction for repository upstream ids (https#redacted=ab12c)
Related pages
- Providers — add explicit providers with API keys to replace zero-config.
- Auth — add project-level authentication before exposing eRPC externally.
- Rate limiters — protect public endpoints from overuse.
- Failsafe policies — hedge, retry, timeout applied on top of any provider.
- URL structure & routing — how
/<project>/<arch>/<chainId>paths are parsed.