ufo

Lightweight, dependency-free URL utilities for parsing, joining, normalizing, and manipulating URLs across Node, browser, and Deno.

Library
npm
v1.6.4
1,301 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
56 /100 Fair
Development Activity 48
Maintenance 20
Community 56
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
74 /100 Good
Architecture 78
Code Quality 85
Innovation 68
Learning Curve 65

ufo is a small, dependency-free utility library for working with URLs in JavaScript and TypeScript. It provides a comprehensive set of pure functions for parsing, encoding, joining, normalizing, and comparing URLs, covering edge cases like protocol-relative URLs, repeated query keys, punycode hostnames, and dangerous script protocols that the native URL API handles inconsistently or not at all.

Maintained by the unjs ecosystem (the team behind Nuxt, Nitro, and h3), ufo is used as a foundational primitive across many unjs packages and is downloaded tens of millions of times a week. It ships as a tiny, side-effect-free ESM/CJS dual package with full TypeScript types, making it a common building block for routers, HTTP clients, and static site generators that need consistent, predictable URL handling in Node.js, browsers, and Deno.

What You Get

  • Parsing utilities - parseURL, parsePath, parseAuth, parseHost, and parseFilename break a URL string into protocol, auth, host, pathname, search, and hash components without throwing on partial or relative input.
  • Encoding/decoding helpers - encode, encodePath, encodeHost, encodeQueryKey/Value, and their decode counterparts handle percent-encoding and punycode consistently across path, query, and hash segments.
  • Query string utilities - parseQuery and stringifyQuery convert between query strings and plain objects, correctly handling repeated keys as arrays.
  • URL manipulation helpers - joinURL, joinRelativeURL, resolveURL, withQuery, withProtocol, withBase/withoutBase, and slash/fragment helpers (withTrailingSlash, withoutHost, etc.) let you compose and rewrite URLs without manual string surgery.
  • Safety checks - isScriptProtocol flags dangerous blob:/data:/javascript:/vbscript: protocols, and hasProtocol/isRelative/isEqual support validating and comparing arbitrary URL-like strings.

Common Use Cases

  • Normalizing user-supplied or third-party URLs before storing or rendering them, including query string re-encoding and double-slash cleanup.
  • Building routers, middleware, or static-site generators (as used internally by Nuxt, Nitro, and h3) that need to join base paths with relative segments correctly.
  • Rewriting or redirecting URLs - swapping protocols, adding/removing trailing slashes, or stripping hosts - without pulling in the full WHATWG URL object.
  • Sanitizing links against script-injection protocols (javascript:, data:, vbscript:) in user-generated content pipelines.

Under The Hood

Architecture The package is organized as a flat set of five focused modules (encoding.ts, parse.ts, query.ts, url.ts, utils.ts) re-exported from a single index.ts, each exposing pure, stateless functions that operate on plain strings and a handful of small interfaces (ParsedURL, ParsedPath, ParsedAuth, ParsedHost, QueryObject) defined in parse.ts and query.ts. There is no class hierarchy or dependency injection beyond a deprecated $URL wrapper in url.ts, which itself composes the functional parse/encode/query utilities rather than introducing new state. Data flows one-directionally - a raw string goes in, a parsed or encoded string (or plain object) comes out - with no internal caching or shared global state, consistent with the package’s declared sideEffects: false. This makes any single module (for example, the regex-based parseURL) safely replaceable without rippling through the rest of the codebase.

Tech Stack Written in TypeScript targeting ESNext modules, built with unbuild (a Rollup-based bundler) into dual ESM (.mjs) and CJS (.cjs) outputs with generated .d.ts declarations, and using automd to keep the README’s function reference in sync with JSDoc comments in src. There are zero runtime dependencies; devDependencies cover linting (eslint plus eslint-config-unjs), formatting (prettier), testing (vitest with @vitest/coverage-v8 and compile-time assertions via a dedicated types.test-d.ts), and release automation (changelogen). The project uses pnpm as its package manager and runs CI on GitHub Actions (Node 20), executing lint, build, and a coverage-instrumented vitest run uploaded to Codecov on every push.

Code Quality Tests are extensive, spanning thirteen test files that each target a specific module (parsing, encoding, joining, normalizing, punycode, query strings, trailing slashes, and more), largely written as table-driven cases that enumerate many edge-case inputs per function rather than one-off assertions. Functions favor returning sensible defaults over throwing on malformed input (parseURL, parseHost, and parseAuth all degrade gracefully), naming is consistent and verb-first (parseX/encodeX/decodeX/withX/withoutX), and the entire surface is written in strict TypeScript with exported interfaces giving callers full type safety. ESLint and Prettier enforce style, and the test script chains linting, type-checking, and the vitest suite together in CI.

API Design ufo’s core idea is treating a URL as a set of small composable pure functions rather than a stateful object, which lets it parse malformed, relative, and protocol-relative strings that would throw with the native new URL() constructor. It fills real gaps in the WHATWG URL API with purpose-built helpers like joinRelativeURL, isScriptProtocol, and withBase/withoutBase. Naming stays highly consistent across roughly thirty exports, which keeps the learning curve manageable despite the surface area, and JSDoc comments carry runnable examples that automd re-injects directly into the README, keeping docs and code from drifting apart. It is a pragmatic ergonomics layer over existing URL parsing rules rather than an invention of new URL semantics.

Used by 6 apps in this directory

Vue
43%
MIT

Alexandrie

Collaboration · Knowledge Management · Note Taking

2,777

The open-source, offline-first Notion, Obsidian & Confluence alternative with multi-tenant teams, OIDC/SSO, and one-command Docker deployment.

View details
86
Repo Health
73
Technical
74
Dependency
Built with
Vue 43%
TypeScript 41%
Go 13%
Updated 1 weeks ago
TypeScript
97%
MIT

likec4

Developer Tools · Devops

5,756

Define your software architecture as code and get always up-to-date, interactive C4 diagrams generated automatically from a DSL.

View details
89
Repo Health
83
Technical
77
Dependency
Built with
TypeScript 97%
Updated 5 days ago
TypeScript
100%
AGPL 3.0

RSSHub

Automation · Social Media

46,339

Turn any website into an RSS feed — social media, streaming platforms, and niche sites all become subscribable in seconds.

View details
94
Repo Health
82
Technical
72
Dependency
Built with
TypeScript 100%
Updated 5 days ago
TypeScript
51%
AGPL 3.0

Sink

Analytics · Bookmarks Archiving

7,173

Serverless link shortener with real-time analytics, powered by Cloudflare

View details
88
Repo Health
80
Technical
0
Dependency
Built with
TypeScript 51%
Vue 47%
Updated 5 days ago
JavaScript
84%
MIT

Unlighthouse

Developer Tools

4,866

An open-source CLI that scans your entire website with Google Lighthouse, using smart sampling and a modern dashboard UI to audit every page instead of one URL at a time.

View details
75
Repo Health
70
Technical
79
Dependency
Built with
JavaScript 84%
TypeScript 11%
Updated 4 days ago
Go
66%
AGPL 3.0

Vikunja

Project Management

5,533

Self-hosted task management with natural-language quick-add, multiple views, and a fully documented REST API — your tasks, your infrastructure, zero lock-in.

View details
86
Repo Health
81
Technical
68
Dependency
Built with
Go 66%
TypeScript 22%
Vue 10%
Updated 4 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers