A shot-reference library can collect several share links for the same clip. Comparing the raw strings makes those references look different when only a query or fragment changed. This Node.js example applies a narrow local URL policy and keeps the video ID as a string. It makes no network requests.
1. Define the reference format you accept
This example accepts parsed HTTPS URLs on tiktok.com or www.tiktok.com with a full /@handle/video/id path. The handle uses letters, digits, dots or underscores, and the ID uses decimal digits. These are application input rules, not a claim to recognize every TikTok link format.
Save these synthetic references as refs.json. They use a fictional handle and illustrative ID; neither link was opened or checked for existence. The two inputs differ in host spelling, query, fragment and trailing slash.
[
"https://www.tiktok.com/@demo.account/video/1234567890123456789?utm_source=notes#example",
"https://tiktok.com/@demo.account/video/1234567890123456789/"
]
2. Parse components before rebuilding a link
Save normalize-reference.mjs. The WHATWG URL parser separates the protocol, hostname, credentials, port and path. Check those parsed components rather than accepting any string that merely contains the text tiktok.com.
export function normalizeTikTokReference(input) {
if (typeof input !== "string" || input.length > 2048 ||
/[\u0000-\u001f\u007f]/.test(input)) {
throw new Error("Expected a URL string without control characters");
}
const u = new URL(input.trim());
if (u.protocol !== "https:" || u.username || u.password || u.port) {
throw new Error("Expected HTTPS without credentials or a custom port");
}
if (!["tiktok.com", "www.tiktok.com"].includes(u.hostname)) {
throw new Error("Unsupported hostname");
}
const match = u.pathname.match(/^\/@([A-Za-z0-9._]+)\/video\/([0-9]+)\/?$/);
if (!match) throw new Error("Expected a full /@handle/video/id path");
const [, handle, videoId] = match;
return {
videoId,
url: `https://www.tiktok.com/@${handle}/video/${videoId}`
};
}
The exact hostname list rejects names such as tiktok.com.example.org. Credentials and non-default ports are outside this policy. The parser normalizes the default HTTPS port 443 to an empty port value, so explicitly writing :443 still passes.
The 2048-character cap is an application budget. Control characters are rejected before trimming outer whitespace. The returned URL is built from the accepted path components and a fixed host, so the input query and fragment are intentionally omitted.
3. Scan a local reference list
Save scan.mjs and run node scan.mjs refs.json. Both rows produce the same normalized URL and the string ID 1234567890123456789. Retain the row index so an error can be matched to the source record.
import { readFile } from "node:fs/promises";
import { normalizeTikTokReference } from "./normalize-reference.mjs";
try {
const file = process.argv[2];
if (!file) throw new Error("Usage: node scan.mjs refs.json");
const refs = JSON.parse(await readFile(file, "utf8"));
if (!Array.isArray(refs)) throw new Error("Expected a reference array");
const result = refs.map((input, index) => {
try {
return { index, ...normalizeTikTokReference(input) };
} catch (error) {
process.exitCode = 2;
return { index, error: error.message };
}
});
console.log(JSON.stringify(result, null, 2));
} catch (error) {
console.error(error.message);
process.exitCode = 2;
}
A row error is reported without dropping the other rows. Any rejected row sets exit code 2. A valid array with only accepted rows exits 0. Missing arguments, unreadable files, malformed JSON and a non-array top level also take the error path.
4. Preserve clip identity without numeric conversion
The ID is captured as text and never passed through Number. Large decimal identifiers can exceed JavaScript’s exact integer range, so an unnecessary numeric conversion can change the reference you store. Keep the string beside the normalized URL in your shot notes.
This helper does not merge records, decide which handle is current or prove that two online pages have the same content. A library can group matching returned IDs for review while preserving the original rows. The next step is to inspect the actual reference through an authorized workflow.
5. Test the policy explicitly
Save test.mjs and run node test.mjs. These 14 synthetic checks cover normalization, ID preservation, ordinary outer spaces, the default port, non-HTTPS inputs, misleading hostnames, credentials, custom ports, short links, missing video paths and control characters.
import assert from "node:assert/strict";
import { normalizeTikTokReference as normalize } from "./normalize-reference.mjs";
const base = "https://www.tiktok.com/@demo.account/video/1234567890123456789";
assert.equal(normalize(base).url, base);
assert.equal(normalize(base + "?utm_source=test#note").url, base);
assert.equal(normalize(base + "/").url, base);
assert.equal(normalize(base.replace("www.tiktok.com", "TIKTOK.COM")).url, base);
assert.equal(normalize(base).videoId, "1234567890123456789");
assert.equal(normalize(" " + base + " ").url, base);
assert.equal(normalize(base.replace("tiktok.com", "tiktok.com:443")).url, base);
assert.throws(() => normalize(base.replace("https:", "http:")), /HTTPS/);
assert.throws(() => normalize(base.replace("tiktok.com", "tiktok.com.example.org")), /hostname/);
assert.throws(() => normalize(base.replace("https://", "https://user:pass@")), /credentials/);
assert.throws(() => normalize(base.replace("tiktok.com", "tiktok.com:8443")), /port/);
assert.throws(() => normalize("https://vm.tiktok.com/example"), /hostname/);
assert.throws(() => normalize("https://www.tiktok.com/@demo.account"), /path/);
assert.throws(() => normalize(base + "\n"), /control/);
console.log("14 checks passed");
Run the command-line wrapper separately too. The example list should exit 0; a missing filename should print usage and exit 2. A mixed list with one short-link input should still report its other rows and exit 2.
6. Keep reference details outside discarded URL fields
Because this policy removes every query parameter and fragment, it also discards any useful information someone placed there. Store your shot timestamp, source note and observation in separate fields. Use the original reference when those URL fields must be preserved.
Short-link hosts such as vm.tiktok.com are rejected. This program does not follow redirects, fetch pages, download clips or bypass access checks. Obtain a full supported link separately if your reference record needs normalization.
The code ran in Node.js 24.20.0 with synthetic URL strings and local JSON files. Tests verify parsing and policy behavior; they do not establish video availability or remote link behavior.
AI assistance was used to draft and edit this article.
Source workflow. PixMind TikTok shot-reference breakdown
Technical reference. Node.js WHATWG URL API
About the author
- The PixMind team shares practical AI image and video workflows. PixMind brings text-to-image, reference-based creation, editing, and video tools into one workspace. Website: https://www.pixmind.io/
Comments
Join the discussionNo comments yet. Be the first to comment.