cors-unlocker
A lightweight npm package for seamlessly managing Cross-Origin Resource Sharing (CORS) settings through the CORS Unlocker browser extension. Perfect for API testing, development, and cross-origin communication.

π Quick Start
Installation
npm install cors-unlocker
yarn add cors-unlocker
pnpm add cors-unlocker
Basic Usage
import appCors from 'cors-unlocker';
const isInstalled = await appCors.isExtInstalled();
const status = await appCors.enable({
credentials: true,
reason: 'Testing cross-origin API requests'
});
console.log('CORS enabled:', status.enabled, 'Credentials:', status.credentials);
π§ How it Works
This package communicates with the CORS Unlocker browser extension through a secure iframe bridge. When CORS is enabled, the extension intelligently modifies HTTP responses by adding necessary Access-Control-Allow-Origin
headers, enabling cross-origin requests without server-side changes.
Key Features
- π‘οΈ Secure Communication: Uses iframe messaging for safe extension interaction
- β‘ Lightweight: Only 1.7KB gzipped - minimal impact on your application
- π― Smart Defaults: Automatically reads extension configuration for credentials
- π« No Timeouts: User confirmation dialogs have no artificial time limits
- π TypeScript Ready: Full type definitions included
- π Reliable: Handles race conditions and communication errors gracefully
π API Reference
Extension Detection
isExtInstalled(): Promise<boolean>
Checks if the CORS Unlocker extension is available in the browser.
try {
const isInstalled = await appCors.isExtInstalled();
if (!isInstalled) {
console.log('Please install the CORS Unlocker extension');
appCors.openStorePage();
}
} catch (error) {
console.error('Extension check failed:', error.message);
}
Returns: Promise<boolean>
Throws: AppCorsError
for communication failures
CORS Status Management
isEnabled(): Promise<{ enabled: boolean, credentials: boolean }>
Retrieves the current CORS status for the active page.
try {
const status = await appCors.isEnabled();
console.log('CORS Status:', status);
} catch (error) {
console.error('Failed to get CORS status:', error.message);
}
Returns: Promise<{ enabled: boolean, credentials: boolean }>
Throws: AppCorsError
for various error conditions
Enable CORS
enable(options?: IEnableOptions): Promise<{ enabled: boolean, credentials: boolean }>
Activates CORS for the current page. May require user confirmation and has no timeout limit to ensure reliable operation.
interface IEnableOptions {
credentials?: boolean;
reason?: string;
}
Examples:
const status = await appCors.enable();
const authStatus = await appCors.enable({
credentials: true,
reason: 'Testing authenticated API endpoints'
});
const basicStatus = await appCors.enable({
credentials: false,
reason: 'Public API testing'
});
console.log('CORS enabled:', authStatus.enabled);
console.log('Credentials allowed:', authStatus.credentials);
Parameters:
credentials
(optional): Enable credential-based requests. If not specified, uses the extension's default setting
reason
(optional): Description shown to user during confirmation dialog
Returns: Promise<{ enabled: boolean, credentials: boolean }>
- The resulting CORS status
Throws: AppCorsError
for various error conditions including user cancellation
Note: This method may require user confirmation and has no timeout limit to avoid race conditions. The operation completes when the user responds or a natural system timeout occurs.
Disable CORS
disable(): Promise<void>
Safely disables CORS for the current page.
try {
await appCors.disable();
console.log('CORS disabled successfully');
} catch (error) {
console.error('Failed to disable CORS:', error.message);
}
Returns: Promise<void>
Throws: AppCorsError
for various error conditions
Extension Management
openExtOptions(): Promise<void>
Opens the extension's options/settings page.
try {
await appCors.openExtOptions();
} catch (error) {
console.error('Failed to open options:', error.message);
}
openStorePage(): void
Opens the browser's extension store page for CORS Unlocker installation.
appCors.openStorePage();
π― Practical Examples
Basic API Testing
import appCors from 'cors-unlocker';
async function testAPI() {
try {
if (!(await appCors.isExtInstalled())) {
console.log('Extension not found, redirecting to store...');
appCors.openStorePage();
return;
}
await appCors.enable({
reason: 'Testing third-party API integration'
});
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log('API Response:', data);
await appCors.disable();
} catch (error) {
console.error('API test failed:', error.message);
}
}
Authenticated Requests
async function testAuthenticatedAPI() {
try {
const status = await appCors.enable({
credentials: true,
reason: 'Testing authenticated endpoints with cookies/headers'
});
if (status.credentials) {
const response = await fetch('https://api.example.com/user/profile', {
credentials: 'include',
headers: {
'Authorization': 'Bearer your-token-here'
}
});
const userData = await response.json();
console.log('User data:', userData);
}
} catch (error) {
console.error('Authenticated request failed:', error.message);
}
}
React Hook Integration
import { useState, useEffect } from 'react';
import appCors from 'cors-unlocker';
function useCORS() {
const [isInstalled, setIsInstalled] = useState(false);
const [corsStatus, setCorsStatus] = useState({ enabled: false, credentials: false });
const [loading, setLoading] = useState(true);
useEffect(() => {
async function checkStatus() {
try {
const installed = await appCors.isExtInstalled();
setIsInstalled(installed);
if (installed) {
const status = await appCors.isEnabled();
setCorsStatus(status);
}
} catch (error) {
console.error('Failed to check CORS status:', error);
} finally {
setLoading(false);
}
}
checkStatus();
}, []);
const toggleCORS = async () => {
try {
if (corsStatus.enabled) {
await appCors.disable();
setCorsStatus({ enabled: false, credentials: false });
} else {
const newStatus = await appCors.enable({
reason: 'Enable CORS for API testing'
});
setCorsStatus(newStatus);
}
} catch (error) {
console.error('Failed to toggle CORS:', error);
}
};
return { isInstalled, corsStatus, loading, toggleCORS };
}
β οΈ Error Handling
All async methods throw AppCorsError
when operations fail. The error object provides detailed information for both debugging and user-friendly error handling.
Error Object Structure
class AppCorsError extends Error {
readonly type: CorsErrorType;
readonly message: string;
}
Error Types Reference
not-installed | Extension is not installed or not responding | User needs to install the CORS Unlocker extension |
user-cancel | User canceled the operation | User clicked "Cancel" in confirmation dialog |
forbidden-origin | Origin is not allowed to use the extension | Website is on extension's blocklist |
rate-limit | Too many requests from this origin | Excessive API calls in short time |
unsupported-origin | Origin protocol is not supported | Only http/https protocols are allowed |
communication-failed | Failed to communicate with extension | Network issues or extension crash |
config-error | Extension configuration error | Missing or invalid extension settings |
invalid-origin | Origin format is invalid | Malformed URL or invalid domain |
inner-error | Internal extension error | Extension bug or unexpected state |
unknown-error | Unexpected error occurred | Fallback for unhandled errors |
Comprehensive Error Handling
import appCors, { AppCorsError } from 'cors-unlocker';
async function robustCORSHandling() {
try {
const status = await appCors.enable({
credentials: true,
reason: 'Testing cross-origin API integration'
});
console.log('β
CORS enabled successfully:', status);
return status;
} catch (error) {
if (error instanceof AppCorsError) {
switch (error.type) {
case 'not-installed':
console.log('π¦ Extension not found. Redirecting to installation...');
appCors.openStorePage();
break;
case 'user-cancel':
console.log('β User canceled the operation');
break;
case 'forbidden-origin':
console.error('π« This website is not allowed to use CORS Unlocker');
break;
case 'rate-limit':
console.warn('β³ Too many requests. Please wait a moment...');
break;
case 'unsupported-origin':
console.error('π CORS Unlocker only works on http/https websites');
break;
case 'communication-failed':
console.error('π‘ Communication failed. Extension may be disabled.');
break;
default:
console.error('β CORS operation failed:', error.message);
console.error('Error type:', error.type);
}
} else {
console.error('π₯ Unexpected error:', error);
}
throw error;
}
}
Graceful Degradation Pattern
async function makeRequestWithCORS(url: string) {
let corsEnabled = false;
try {
if (await appCors.isExtInstalled()) {
await appCors.enable({ reason: 'API request requires CORS' });
corsEnabled = true;
}
} catch (error) {
console.warn('CORS unavailable, falling back to alternative:', error.message);
}
try {
const response = await fetch(url, {
credentials: corsEnabled ? 'include' : 'same-origin'
});
return await response.json();
} catch (fetchError) {
if (!corsEnabled) {
throw new Error(`Request failed. CORS Unlocker extension might help. Original error: ${fetchError.message}`);
}
throw fetchError;
} finally {
if (corsEnabled) {
try {
await appCors.disable();
} catch (error) {
console.warn('Failed to disable CORS:', error.message);
}
}
}
}
π Related Resources
π License
MIT License
Made with β€οΈ for developers who need simple CORS solutions