Smart selector and latency tester for IPFS HTTP gateways (vanilla JS, no dependencies).
Checks gateway availability and performance by fetching only the first byte of a CID (using HTTP Range requests) and aborting stalled requests earlyβmaking latency testing extremely fast and bandwidth-efficient.
Sorts gateways by latency, supports fallback and custom lists, works in any browser or framework.
- Sorts public and custom IPFS gateways by latency
- Automatically picks the best/fastest gateway for a given CID
- Fallback strategy: tries all, picks fastest, randomizes if needed
- Retry logic for failed scans (NEW in v1.3.0)
- User can add and remove their own gateways (persisted in localStorage)
- All gateway lists can be configured at runtime
- Works in plain HTML, Vue, React, Svelte, or any JS app
- Low-level per-gateway check (
measureGateway) - Gateway URL normalization utility (
normalizeGatewayUrl) - No external dependencies
npm install ipfs-smart-gatewayOr use via CDN:
<script src="https://unpkg.com/ipfs-smart-gateway/dist/ipfs-smart-gateway.umd.js"></script>import * as ipfsGateway from 'ipfs-smart-gateway';
ipfsGateway.configure({
stopOnFirstSuccess: true,
persistStorage: true,
timeout: 5000
});
// Overwrite default gateway list
ipfsGateway.setDefaultGateways([
'https://custom.ipfs.net/ipfs/',
'https://another.io/ipfs/'
]);
// Add user gateways
ipfsGateway.setUserGateways([
'https://my-gw.example.com/ipfs/'
]);
// Remove user gateways
ipfsGateway.removeUserGateways([
'https://my-gw.example.com/ipfs/'
]);
// Run latency checks with retry (NEW in v1.3.0)
const gateways = await ipfsGateway.checkGateways({
cid: 'Qm...YourCID...',
retry: 2, // retry up to 2 times if no gateways respond
retryDelay: 1500, // wait 1500 ms between retries
onStart: () => console.log('Starting checks...'),
onSuccess: g => console.log('β
', g.url, g.time, 'ms'),
onFail: g => console.log('β', g.url)
});
console.log('Sorted gateways:', gateways);
// Fastest gateway
const picked = ipfsGateway.getPickedGateway();
console.log('Fastest gateway:', picked);
// Fetch content
const text = await ipfsGateway.fetchFromPicked('Qm...YourCID...');
const json = await ipfsGateway.fetchFromPicked('Qm...JsonCID', 'json');
// Normalize any user-supplied URL
const clean = ipfsGateway.normalizeGatewayUrl('ipfs.io/ipfs/');
console.log('Normalized:', clean); // β https://ipfs.io<script src="https://unpkg.com/ipfs-smart-gateway/dist/ipfs-smart-gateway.umd.js"></script>
<script>
const cid = 'QmYourCID';
ipfsSmartGateway.checkGateways({ cid })
.then(() => {
const best = ipfsSmartGateway.getPickedGateway();
console.log('Best gateway:', best);
return ipfsSmartGateway.fetchFromPicked(cid);
})
.then(content => console.log('Content:', content));
</script>ipfsGateway.configure({
stopOnFirstSuccess: true, // Stop on first working gateway (faster, less traffic)
persistStorage: false, // Don't save anything in localStorage (session only)
timeout: 5000 // Timeout in ms per gateway probe (default: 3000)
});-
setDefaultGateways(array)
Overwrite the built-in default gateway list. -
getDefaultGateways()
Retrieve the current default gateways. -
setUserGateways(array)
Persist a list of user-defined gateways (max 15). -
getUserGateways()
Retrieve the current list of user gateways. -
removeUserGateways(array)
Remove specified gateways from the user list. -
getAllGateways()
Returns combined default + user gateways.
-
checkGateways({ cid, retry, retryDelay, onStart, onSuccess, onFail })
Perform parallel latency and availability checks for the given CID.Parameters
cid(string): IPFS CID to test.retry(number, optional): Number of retry attempts if no gateways respond. Default:0.retryDelay(number, optional): Delay in milliseconds between retries. Default:1000.onStart(function, optional): Callback before any checks.onSuccess(function, optional): Callback for each successful gateway.onFail(function, optional): Callback for each failed gateway.
Returns
An array of available gateways sorted by latency. -
measureGateway(url, cid, timeout?)
Test a single gateway for the given CID and measure response time.Parameters
url(string): The gateway URL (with or without protocol,/ipfs/is not required).cid(string): IPFS CID to test.timeout(number, optional): Timeout in ms for this check (default: global timeout).
Returns
Milliseconds to respond (number), ornullif not available.Example
const ms = await ipfsGateway.measureGateway('https://ipfs.io', 'QmYourCID'); if (ms !== null) { console.log('Gateway is available! Latency:', ms, 'ms'); } else { console.log('Gateway is not available for this CID'); }
-
getSortedGateways()
Returns gateways sorted by measured latency (fastest first). -
getPickedGateway()
Returns the fastest gateway URL, ornullif none. -
setPickedGateway(url)
Manually set the picked gateway. -
loadUserGatewaysFromCache()
Load user gateways from localStorage. -
loadPickedGatewayFromCache()
Load the last picked gateway from localStorage.
-
fetchFromPicked(cid, format = 'text')
Fetches from the currently picked gateway.
formatmay be'text','json', or'blob'. -
fetchWithFallback(cid, format = 'text')
Attempts fetch in order of latency, then random fallback gateways.
- normalizeGatewayUrl(raw)
Normalize / clean up any gateway URL.- Adds
https://if the scheme is missing. - Removes trailing
/ipfsor/ipfs/. - Trims extra slashes.
Returns the normalized URL string.
- Adds
Basic: Check and pick fastest gateway
await ipfsSmartGateway.checkGateways({ cid: 'QmYourCID' });
const sorted = ipfsSmartGateway.getSortedGateways();
console.log('Sorted by latency:', sorted);
const picked = ipfsSmartGateway.getPickedGateway();
const text = await ipfsSmartGateway.fetchFromPicked('QmYourCID');Test a single gateway
const ms = await ipfsSmartGateway.measureGateway('https://ipfs.io', 'QmYourCID');
if (ms !== null) {
console.log('Gateway is available! Latency:', ms, 'ms');
} else {
console.log('Gateway is not available for this CID');
}Add user gateway and test
ipfsSmartGateway.setUserGateways(['https://my-gw.example.com/ipfs/']);
await ipfsSmartGateway.checkGateways({ cid: 'QmYourCID' });Remove user gateways
ipfsSmartGateway.removeUserGateways([
'https://my-gw.example-1.com/ipfs/',
'https://my-gw.example-2.com/ipfs/'
]);Fetch as JSON or Blob
const data = await ipfsSmartGateway.fetchFromPicked('QmYourJson', 'json');
const blob = await ipfsSmartGateway.fetchFromPicked('QmFile', 'blob');Retry if no gateways are found immediately
const gateways = await ipfsSmartGateway.checkGateways({
cid: 'QmYourCID',
retry: 1,
retryDelay: 2000
});
console.log('Available gateways after retry:', gateways);Listen to gateway check events
await ipfsSmartGateway.checkGateways({
cid: 'QmTest',
onStart: () => console.log('Started...'),
onSuccess: g => console.log('β
', g.url, g.time),
onFail: g => console.log('β', g.url)
});If storage is enabled, the following keys are used in localStorage:
ipfs-smart-gateway:user-gatewaysipfs-smart-gateway:picked
MIT
Note: Some of this documentation and initial scaffolding was generated in collaboration with AI (OpenAIβs ChatGPT).