How to validate URL in JavaScript
URL validation is essential for web applications that handle user-submitted links, API endpoints, or external resources, ensuring data integrity and preventing security issues. With over 25 years of experience in software development and as the creator of CoreUI, I’ve implemented URL validation in countless forms, admin panels, and content management systems. From my expertise, the most reliable approach is to use JavaScript’s built-in URL constructor, which provides comprehensive validation and parsing capabilities. This method is robust, standards-compliant, and handles edge cases that regex patterns often miss.
Use the URL constructor to validate URLs with built-in error handling.
const isValidUrl = (string) => {
try {
new URL(string)
return true
} catch (err) {
return false
}
}
console.log(isValidUrl('https://example.com')) // true
console.log(isValidUrl('not a url')) // false
How It Works
The URL constructor parses the provided string and throws a TypeError if it’s not a valid URL. By wrapping the constructor in a try-catch block, we can return true for valid URLs and false for invalid ones. This approach validates the protocol, hostname, and overall structure according to web standards.
Validating with Base URL
Handle relative URLs by providing a base URL as the second parameter:
const isValidUrl = (string, baseUrl) => {
try {
new URL(string, baseUrl)
return true
} catch (err) {
return false
}
}
console.log(isValidUrl('/api/users', 'https://example.com')) // true
console.log(isValidUrl('invalid', 'https://example.com')) // false
The base URL provides context for resolving relative URLs. The URL constructor combines the base URL with the relative path, validating the result. This is particularly useful when validating API endpoints or internal links that don’t include the full domain.
Validating Specific Protocols
Restrict validation to specific protocols like http or https:
const isValidHttpUrl = (string) => {
try {
const url = new URL(string)
return url.protocol === 'http:' || url.protocol === 'https:'
} catch (err) {
return false
}
}
console.log(isValidHttpUrl('https://example.com')) // true
console.log(isValidHttpUrl('ftp://example.com')) // false
console.log(isValidHttpUrl('javascript:alert(1)')) // false
After validating the URL structure, check the protocol property to ensure it matches your requirements. This prevents malicious URLs with protocols like javascript: or data: from being accepted, which is crucial for security when handling user input.
Using Regex for Basic Validation
For simpler cases or older browser support, use a regex pattern:
const isValidUrl = (string) => {
const pattern = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/
return pattern.test(string)
}
console.log(isValidUrl('https://example.com')) // true
console.log(isValidUrl('http://sub.example.com')) // true
console.log(isValidUrl('not-a-url')) // false
This regex pattern checks for http/https protocols, valid domain names, and optional paths. While less comprehensive than the URL constructor, it works in all JavaScript environments and doesn’t throw exceptions. The pattern allows common URL characters and validates basic structure.
Validating URL Parts
Extract and validate specific parts of a URL:
const validateUrlParts = (string) => {
try {
const url = new URL(string)
return {
valid: true,
protocol: url.protocol,
hostname: url.hostname,
pathname: url.pathname,
hasValidDomain: url.hostname.includes('.')
}
} catch (err) {
return { valid: false }
}
}
const result = validateUrlParts('https://api.example.com/users')
console.log(result)
// { valid: true, protocol: 'https:', hostname: 'api.example.com',
// pathname: '/users', hasValidDomain: true }
The URL object provides properties for all URL components. This allows validation of specific requirements like checking for a valid top-level domain using hostname.includes('.'), ensuring the path starts with /, or verifying the presence of query parameters.
Validating Form Input
Provide real-time feedback as users enter URLs:
const urlInput = document.getElementById('website')
const errorMessage = document.getElementById('url-error')
urlInput.addEventListener('input', (e) => {
const url = e.target.value
if (!url) {
errorMessage.textContent = ''
return
}
try {
const parsed = new URL(url)
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
errorMessage.textContent = ''
urlInput.classList.remove('invalid')
} else {
errorMessage.textContent = 'Please enter an http or https URL'
urlInput.classList.add('invalid')
}
} catch (err) {
errorMessage.textContent = 'Please enter a valid URL'
urlInput.classList.add('invalid')
}
})
This validation runs on every input change, immediately showing errors for invalid URLs. The check for empty input prevents showing errors before the user starts typing. Protocol validation ensures only web URLs are accepted, rejecting potentially dangerous protocols.
Checking URL Reachability
Verify that a URL actually exists and is accessible:
const isUrlReachable = async (url) => {
try {
const response = await fetch(url, { method: 'HEAD' })
return response.ok
} catch (err) {
return false
}
}
// Usage
const url = 'https://example.com'
const reachable = await isUrlReachable(url)
console.log(reachable ? 'URL is accessible' : 'URL is not accessible')
The HEAD request checks if the URL is reachable without downloading the full content. This is useful for validating external links in content management systems or checking API endpoints. Note that this requires network access and adds latency, so use it sparingly.
Best Practice Note
This is the same URL validation approach we use in CoreUI form components to ensure link inputs are valid before submission. The URL constructor is the most reliable method for modern applications, handling internationalized domain names, IPv6 addresses, and complex URL structures that regex patterns struggle with. For comprehensive input validation, combine URL checking with how to validate email in JavaScript and how to prevent XSS attacks in JavaScript for secure user input handling. For production forms, consider using CoreUI’s CFormInput component which includes built-in validation patterns. Always validate URLs on the server side as well, since client-side validation can be bypassed.



