React Native URL Polyfill
react-native-url-polyfill is a lightweight and robust polyfill for the WHATWG URL Standard, specifically optimized for React Native environments. It addresses limitations and inconsistencies in React Native's built-in URL implementation, which can lead to unexpected errors with complex URL parsing or specific properties like `searchParams` and `hostname`. The current stable version is 3.0.0. While there isn't a fixed monthly cadence, the project actively releases major versions for significant updates like new Web API features (e.g., `URL.canParse()`) and minor/patch versions for bug fixes and compatibility improvements. Key differentiators include its lightweight nature (stripping Unicode support to reduce bundle size to ~40KB, down from 372KB for the full `whatwg-url` package), trustworthiness (following the spec, backed by unit and Detox e2e tests), and explicit support for Hermes, Expo, and Blob objects.
Common errors
-
TypeError: URLSearchParams.get is not implemented, js engine: hermes
cause The `URLSearchParams` API or specific methods like `get` are not fully implemented in React Native's default URL polyfill or an older version of `react-native-url-polyfill` is being used with Hermes.fixEnsure you have `react-native-url-polyfill` installed and `import 'react-native-url-polyfill/auto';` is placed at the very top of your application's entry file (e.g., `index.js`). Also, update to version 1.1.2 or newer for better Hermes compatibility. -
TypeError: URL.canParse is not a function
cause The `URL.canParse()` static method was introduced in `react-native-url-polyfill` v3.0.0 and is not present in earlier versions or the global polyfill has not been applied correctly.fixUpgrade `react-native-url-polyfill` to version 3.0.0 or higher. Confirm that `import 'react-native-url-polyfill/auto';` is correctly placed at the application entry point to ensure the global `URL` object is extended with `canParse`. -
URL cannot handle "localhost" domain for base url
cause This is a known issue with React Native's *native* URL implementation, which `react-native-url-polyfill` aims to address. It indicates the polyfill is either not active or not correctly overriding the native implementation.fixDouble-check that `import 'react-native-url-polyfill/auto';` is the very first import in your main React Native entry file (e.g., `index.js` or `App.js`) to ensure it applies before other code uses the `URL` object.
Warnings
- gotcha Despite v2.0.0 being a major version, the release notes stated 'we don't expect any breaking changes. The upgrade should be seamless.' However, its behavior changed regarding `react-native-url-polyfill/auto` on web platforms (e.g., `react-native-web`), where it would previously apply the polyfill but now acts as a no-op. While not breaking *functionality* for React Native, it changes cross-platform polyfill application.
- breaking Version 3.0.0 introduces `URL.canParse()`, which, while a standard Web API addition, might lead to issues in environments that do not inherently support it (like older React Native versions or certain test runners that don't polyfill it). This is more of a feature addition, but if you upgrade `react-native-url-polyfill` and your React Native environment's baseline is too old for the `URL` spec it polyfills, it *could* technically break if you try to use this specific feature without the polyfill being active.
- gotcha The polyfill, by design, strips out Unicode support for hostnames to maintain a lightweight footprint on mobile devices. This means non-ASCII characters in the hostname portion of a URL are not supported and may lead to incorrect parsing or errors.
- gotcha An incompatibility with the Hermes JavaScript engine was fixed in version 1.1.2. Older versions of the polyfill might exhibit unexpected behavior or errors when running on Hermes.
- gotcha Prior to version 1.1.0, the package included `lodash.sortby` as a dependency, increasing its bundle size. This dependency was removed in v1.1.0 to reduce the package size by approximately 13 KB.
Install
-
npm install react-native-url-polyfill -
yarn add react-native-url-polyfill -
pnpm add react-native-url-polyfill
Imports
- auto-polyfill
require('react-native-url-polyfill/auto');import 'react-native-url-polyfill/auto';
- URL
import URL from 'react-native-url-polyfill'; // Incorrect default export
import { URL, URLSearchParams } from 'react-native-url-polyfill'; - URL.canParse
import 'react-native-url-polyfill/auto'; URL.canParse('https://example.com');
Quickstart
import 'react-native-url-polyfill/auto';
import { useEffect, useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
const App = () => {
const [parsedUrl, setParsedUrl] = useState('');
const [searchParam, setSearchParam] = useState('');
const [canParseResult, setCanParseResult] = useState('');
useEffect(() => {
const urlString = 'https://www.example.com/path?query=value&id=123#fragment';
try {
const url = new URL(urlString);
setParsedUrl(`Origin: ${url.origin}, Host: ${url.host}, Path: ${url.pathname}`);
setSearchParam(`Query 'id': ${url.searchParams.get('id')}`);
// Test URL.canParse (introduced in v3.0.0)
const validParse = URL.canParse(urlString);
const invalidParse = URL.canParse('invalid-url');
setCanParseResult(`Can parse valid URL: ${validParse}, Can parse invalid URL: ${invalidParse}`);
} catch (e) {
setParsedUrl(`Error parsing URL: ${e.message}`);
}
}, []);
return (
<View style={styles.container}>
<Text style={styles.title}>react-native-url-polyfill Demo</Text>
<Text style={styles.text}>Original URL: https://www.example.com/path?query=value&id=123#fragment</Text>
<Text style={styles.text}>Parsed URL Info: {parsedUrl}</Text>
<Text style={styles.text}>Search Param Info: {searchParam}</Text>
<Text style={styles.text}>URL.canParse Result: {canParseResult}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#f5fcff',
},
title: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 10,
},
text: {
fontSize: 16,
marginBottom: 5,
textAlign: 'center',
},
});
export default App;