Parse GitHub URLs and GitHub repository remotes into structured metadata for repositories, files, directories, issues, pull requests, commits, releases, comparisons, discussions, and GitHub Actions workflow runs.
github-url-parser normalizes GitHub remotes, shorthand repository specifiers, and browser URLs for files, directories, issues, pull requests, commits, releases, comparisons, discussions, and workflow runs. It includes TypeScript declarations, makes no network requests, and returns null for unsupported or non-GitHub input.
- Parse GitHub repository URLs, SSH remotes, shortcuts, and
user/repospecifiers. - Extract normalized owner, repo, browse, API, HTTPS, SSH, and raw file URLs.
- Recognize GitHub issues, pull requests, commits, releases, compare pages, discussions, and Actions workflow runs.
- Work offline with no GitHub API requests and no runtime configuration.
- Ship TypeScript declarations with a small ESM-only package surface.
npm install github-url-parserimport { parseGitHubUrl } from "github-url-parser";
const result = parseGitHubUrl(
"https://github.com/AlightSoulmate/github-url-parser/blob/main/package.json"
);
console.log(result);{
owner: "AlightSoulmate",
repo: "github-url-parser",
domain: "github.com",
type: "github",
kind: "blob",
committish: "main",
repoUrl: "https://github.com/AlightSoulmate/github-url-parser",
browseUrl: "https://github.com/AlightSoulmate/github-url-parser/blob/main/package.json",
apiUrl: "https://api.github.com/repos/AlightSoulmate/github-url-parser/contents/package.json?ref=main",
httpsUrl: "https://github.com/AlightSoulmate/github-url-parser.git",
sshUrl: "git@github.com:AlightSoulmate/github-url-parser.git",
ref: "main",
path: "package.json",
rawUrl: "https://raw.githubusercontent.com/AlightSoulmate/github-url-parser/main/package.json"
}Invalid URLs, unsupported GitHub pages, and non-GitHub hosted Git URLs return null.
parseGitHubUrl("https://example.com/foo/bar");
// null
parseGitHubUrl("https://gitlab.com/user/repo");
// nullParses url and returns a metadata object for supported GitHub URLs. Returns null when the input cannot be parsed as a supported GitHub resource.
The package exports parseGitHubUrl as a named ESM export.
TypeScript declarations are included.
Repository and remote specifiers are parsed through hosted-git-info:
https://github.com/user/repo
https://github.com/user/repo.git
git@github.com:user/repo.git
github:user/repo
user/repoGitHub browser URLs are parsed directly:
https://github.com/user/repo
https://github.com/user/repo/tree/main/src
https://github.com/user/repo/blob/main/src/index.js
https://github.com/user/repo/issues/123
https://github.com/user/repo/pull/456
https://github.com/user/repo/commit/abc123
https://github.com/user/repo/compare/main...dev
https://github.com/user/repo/releases
https://github.com/user/repo/releases/tag/v1.0.0
https://github.com/user/repo/releases/latest
https://github.com/user/repo/tags
https://github.com/user/repo/branches
https://github.com/user/repo/discussions
https://github.com/user/repo/discussions/123
https://github.com/user/repo/actions
https://github.com/user/repo/actions/runs/123456789Every successful parse includes the base repository fields:
{
owner: "user",
repo: "repo",
domain: "github.com",
type: "github",
kind: "repo",
committish: null,
repoUrl: "https://github.com/user/repo",
browseUrl: "https://github.com/user/repo",
apiUrl: "https://api.github.com/repos/user/repo",
httpsUrl: "https://github.com/user/repo.git",
sshUrl: "git@github.com:user/repo.git"
}Field notes:
ownerandrepoidentify the repository.kindidentifies the parsed resource type.committishisnullunless the URL carries a branch, tag, commit, or other ref-like value.repoUrlalways points to the repository page.browseUrlpoints to the parsed GitHub page or repository browser URL.apiUrlis the closest related GitHub REST API endpoint generated from the URL. For resources without a dedicated REST endpoint, it falls back to the repository API URL. The package does not call the GitHub API.httpsUrlandsshUrlare normalized Git remote URLs.
Additional fields are included for specific resource types:
kind |
URL type | Additional fields |
|---|---|---|
repo |
Repository or remote | None |
blob |
File browser URL | ref, path, rawUrl |
tree |
Directory browser URL | ref, path, rawUrl: null |
issue |
Issue URL | number |
pull |
Pull request URL | number |
commit |
Commit URL | sha |
release |
Release tag URL | tag |
releases |
Releases collection | collection |
latest-release |
Latest release URL | selector |
compare |
Compare URL | range, baseRef, headRef |
tags |
Tags collection | collection |
branches |
Branches collection | collection |
discussions |
Discussions collection | collection |
discussion |
Discussion URL | number |
actions |
Actions collection | collection |
workflow-run |
Workflow run URL | runId |
parseGitHubUrl("git@github.com:user/repo.git");
// {
// owner: "user",
// repo: "repo",
// domain: "github.com",
// type: "github",
// kind: "repo",
// committish: null,
// repoUrl: "https://github.com/user/repo",
// browseUrl: "https://github.com/user/repo",
// apiUrl: "https://api.github.com/repos/user/repo",
// httpsUrl: "https://github.com/user/repo.git",
// sshUrl: "git@github.com:user/repo.git"
// }parseGitHubUrl("github:AlightSoulmate/github-url-parser#v0.1.0");
// {
// owner: "AlightSoulmate",
// repo: "github-url-parser",
// domain: "github.com",
// type: "github",
// kind: "repo",
// committish: "v0.1.0",
// repoUrl: "https://github.com/AlightSoulmate/github-url-parser",
// browseUrl: "https://github.com/AlightSoulmate/github-url-parser/tree/v0.1.0",
// apiUrl: "https://api.github.com/repos/AlightSoulmate/github-url-parser",
// httpsUrl: "https://github.com/AlightSoulmate/github-url-parser.git#v0.1.0",
// sshUrl: "git@github.com:AlightSoulmate/github-url-parser.git#v0.1.0"
// }parseGitHubUrl("https://github.com/user/repo/issues/123");
// {
// owner: "user",
// repo: "repo",
// domain: "github.com",
// type: "github",
// kind: "issue",
// committish: null,
// repoUrl: "https://github.com/user/repo",
// browseUrl: "https://github.com/user/repo/issues/123",
// apiUrl: "https://api.github.com/repos/user/repo/issues/123",
// httpsUrl: "https://github.com/user/repo.git",
// sshUrl: "git@github.com:user/repo.git",
// number: 123
// }parseGitHubUrl("https://github.com/user/repo/pull/456");
// {
// owner: "user",
// repo: "repo",
// domain: "github.com",
// type: "github",
// kind: "pull",
// committish: null,
// repoUrl: "https://github.com/user/repo",
// browseUrl: "https://github.com/user/repo/pull/456",
// apiUrl: "https://api.github.com/repos/user/repo/pulls/456",
// httpsUrl: "https://github.com/user/repo.git",
// sshUrl: "git@github.com:user/repo.git",
// number: 456
// }parseGitHubUrl("https://github.com/user/repo/blob/main/src/index.js");
// {
// owner: "user",
// repo: "repo",
// domain: "github.com",
// type: "github",
// kind: "blob",
// committish: "main",
// repoUrl: "https://github.com/user/repo",
// browseUrl: "https://github.com/user/repo/blob/main/src/index.js",
// apiUrl: "https://api.github.com/repos/user/repo/contents/src/index.js?ref=main",
// httpsUrl: "https://github.com/user/repo.git",
// sshUrl: "git@github.com:user/repo.git",
// ref: "main",
// path: "src/index.js",
// rawUrl: "https://raw.githubusercontent.com/user/repo/main/src/index.js"
// }parseGitHubUrl("https://github.com/user/repo/compare/main...dev");
// {
// owner: "user",
// repo: "repo",
// domain: "github.com",
// type: "github",
// kind: "compare",
// committish: null,
// repoUrl: "https://github.com/user/repo",
// browseUrl: "https://github.com/user/repo/compare/main...dev",
// apiUrl: "https://api.github.com/repos/user/repo/compare/main...dev",
// httpsUrl: "https://github.com/user/repo.git",
// sshUrl: "git@github.com:user/repo.git",
// range: "main...dev",
// baseRef: "main",
// headRef: "dev"
// }- Only
github.comURLs are supported. - API URLs and raw file URLs are generated strings; they are not validated with the GitHub API.
- Unsupported GitHub pages, malformed issue or pull request numbers, and invalid compare ranges return
null.
npm testRuns both AVA and TSD test.
MIT