๐ Making API Calls in Chrome Extensions
Making API calls is essential for many Chrome extensions. This guide shows you how to do it securely and efficiently using modern JavaScript practices.
๐งฐ Prerequisites
Make sure your extension is properly set up. New to this? Start with our beginner guide.
๐ช Steps to Make API Calls
1. Request Permissions
In your manifest.json
:
{
"manifest_version": 3,
"name": "My API Extension",
"version": "1.0",
"permissions": ["https://api.example.com/"],
"host_permissions": ["https://api.example.com/"]
}
Replace the URL with your API base path.
2. Make the API Call
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error(\`HTTP error! status: \${response.status}\`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
fetchData();
3. Handle CORS
To avoid CORS issues, call the API from a service worker rather than a content script.
๐ Making API Calls from Different Contexts
โ From Service Workers
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'fetchData') {
fetchDataAndRespond(sendResponse);
return true;
}
});
async function fetchDataAndRespond(sendResponse) {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error(\`HTTP error! status: \${response.status}\`);
const data = await response.json();
sendResponse({data});
} catch (error) {
sendResponse({error: error.toString()});
}
}
โ From Content Scripts
async function fetchDataFromBackground() {
try {
const response = await chrome.runtime.sendMessage({action: 'fetchData'});
if (response.data) {
console.log(response.data);
} else {
console.error(response.error);
}
} catch (error) {
console.error('Error:', error);
}
}
fetchDataFromBackground();
โ Best Practices
- Use
async/await
for readability - Handle errors with
try/catch
- Throttle or cache to respect rate limits
- Store API keys securely (use
chrome.storage
) - Handle offline scenarios gracefully
๐ Security Considerations
- Never hardcode sensitive API keys
- Use HTTPS for all requests
- Validate and sanitize all received data
- Only request necessary permissions
โ๏ธ Using the Fetch API with Options
async function postData(url = '', data = {}) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data),
});
if (!response.ok) throw new Error(\`HTTP error! status: \${response.status}\`);
return await response.json();
} catch (error) {
console.error('Error:', error);
}
}
postData('https://api.example.com/data', { answer: 42 })
.then((data) => console.log(data));
๐ Handling Authentication
async function fetchWithAuth(url) {
const API_KEY = await getApiKey(); // Implement securely
try {
const response = await fetch(url, {
headers: { 'Authorization': \`Bearer \${API_KEY}\` }
});
if (!response.ok) throw new Error(\`HTTP error! status: \${response.status}\`);
return await response.json();
} catch (error) {
console.error('Error:', error);
}
}
๐งพ Conclusion
You now know how to:
- Make secure API calls
- Use fetch with async/await
- Handle CORS issues with service workers
- Follow best practices for security and performance
Continue building dynamic extensions by combining APIs with service workers, content scripts, and UI pages.
Happy coding! ๐