Blogg / Utvecklarguide
Så tolkar och normaliserar du profiladresser i sociala medier (Instagram, TikTok, YouTube, X)
Kreatörer klistrar in sina profillänkar i alla tänkbara former: med och utan www, från mobilappen med spårningsparametrar, som kortlänkar, som gamla twitter.com-adresser eller som en länk till ett inlägg i stället för till profilen. Om din produkt sparar strängarna precis som de kommer in dyker samma kreatör upp tre gånger och dina joins missar i tysthet. Den här guiden visar hur du gör om en profiladress från Instagram, TikTok, YouTube eller X till en plattform, ett handle eller kanal-ID och en kanonisk URL, med testad kod i JavaScript och Python.
Varför det är viktigt att normalisera profiladresser
En profiladress är en identifierare, och identifierare fungerar bara när de skrivs på ett enda sätt. https://www.instagram.com/natgeo/, instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA== och https://m.instagram.com/natgeo pekar alla på samma konto, men som strängar är de tre olika värden.
- Dubbletter. När en kreatör registrerar sig två gånger, eller när två personer i teamet lägger till samma influencer i en kampanj, vill du ha en post, inte två.
- Joins. Att matcha ditt CRM mot en export från ett annat verktyg fungerar bara om båda sidor använder samma nyckel.
- Stoppa dålig indata tidigt. En länk till en reel, en söksida eller en inloggningsskärm är ingen profil. Det är billigare att fånga det när datan matas in än att städa upp i efterhand.
- Anrop till API:er. Officiella API:er vill ha ett handle eller ett ID, inte en URL med spårningsparametrar.
Målet är en liten och strikt funktion: den accepterar det användare faktiskt klistrar in, returnerar ett normaliserat resultat för riktiga profiladresser och returnerar null för allt annat.
URL-formerna du kommer att stöta på
Formerna nedan kontrollerades mot de skarpa webbplatserna i oktober 2026. Plattformarna ändrar sin routing utan förvarning, så se det här som en ögonblicksbild och håll dina testfall uppdaterade.
- Profiler ligger på
https://www.instagram.com/<handle>/. Värdarnainstagram.comochm.instagram.comomdirigerar tillwww.instagram.com. - Länkar som delas från appen har ofta en parameter
?igsh=. Ta bort hela frågesträngen och fragmentet. - Inlägg är
/p/<code>/, reels är/reel/<code>/och stories är/stories/<handle>/<id>/. Inget av dessa är en profiladress, även när handlet finns i sökvägen. - App-rutter som
/explore/,/accounts/och/direct/delar första segmentet i sökvägen med handles, så du behöver en lista med reserverade ord. Listan i koden nedan är inte heltäckande.
TikTok
- Profiler är
https://www.tiktok.com/@<handle>. Värdentiktok.comutan prefix omdirigerar tillwww. - Videor är
/@<handle>/video/<id>. Handlet är upphovspersonen, men URL:en är en videolänk, så tolken nedan avvisar den. - Kortlänkar på
vm.tiktok.com,vt.tiktok.comochwww.tiktok.com/t/<code>/innehåller inget handle alls. Du måste följa HTTP-omdirigeringen för att se vart de leder och sedan tolka den slutliga URL:en. - En sökväg utan
@(till exempeltiktok.com/khaby.lame) är ingen profiladress.
YouTube
- Handle-adresser:
https://www.youtube.com/@<handle>. Enligt YouTubes hjälpcenter blir ett handle automatiskt kanalens URL. - Adresser med kanal-ID:
https://www.youtube.com/channel/UC.... Det här är den stabila formen. I praktiken är kanal-ID:n 24 tecken långa och börjar medUC. Google dokumenterar inte formatet, så kontrollen nedan är en rimlighetsgräns, inte en regel. - Äldre former:
/user/<username>och/c/<customname>. Båda fungerar fortfarande, och hjälpcentret säger att äldre personliga adresser fortsätter att fungera. Ingen av dem ger dig kanal-ID:t utan ett uppslag. - En adress som bara är
youtube.com/<name>fungerar också fortfarande för vissa kanaler, men den delar namnrymd med webbplatsens egna rutter, så tolken nedan accepterar den inte. - Flikar som
/@handle/videosoch/channel/UC.../featuredhör till kanalen och är säkra att acceptera. m.youtube.comomdirigerar tillwww.youtube.com. Videolänkar (/watch?v=,/shorts/,youtu.be/<id>) är inte kanaler.
X (tidigare Twitter)
- Profiler är
https://x.com/<handle>.twitter.com,www.twitter.com,www.x.com,mobile.twitter.comochmobile.x.comomdirigerar alla till en profil påx.comellertwitter.com, så behandla dem som en och samma plattform. - Inlägg är
/<handle>/status/<id>. Precis som TikTok-videor anger de upphovspersonen men är inga profiladresser. - App-rutter som
/home,/explore,/search,/settings,/notifications,/messagesoch allt under/i/är inga handles. - Delade länkar får ofta parametrarna
?s=och?t=. Ta bort dem.
Teckenregler för handles per plattform
Att validera handlet fångar stavfel och de flesta sökvägar som inte är profiler. Använd plattformarnas egna regler där de publicerar dem, och håll kontrollerna generösa där de inte gör det, så att du aldrig avvisar ett riktigt konto.
| Plattform | Tillåtna tecken | Längd | Skiftläge | Källa |
|---|---|---|---|---|
| Bokstäver, siffror, punkter, understreck | 30 anges ofta, men finns inte i Instagrams hjälpsidor | Behandla som skiftlägesokänsligt, spara i gemener | Instagrams hjälpcenter nämner punkter, siffror och understreck | |
| TikTok | Bokstäver, siffror, understreck, punkter, får inte sluta med punkt | 2 till 24 | Skiftlägesokänsligt i adresser (@TikTok leder till tiktok) | TikTok Support, byta användarnamn |
| YouTube | Bokstäver eller siffror från språk som stöds, plus understreck, bindestreck, punkter och latinska mittpunkter (inte först eller sist) | 3 till 30 för de flesta skriftsystem, kortare gränser för han, hangul och några andra skriftsystem | Inte skiftlägeskänsligt | YouTube-hjälp, riktlinjer för handles |
| X | Bokstäver, siffror och understreck | Upp till 15, nya användarnamn måste vara längre än 4, men äldre korta handles finns | Inte skiftlägeskänsligt (x.com/JACK kanoniseras till x.com/jack) | X Help Center, regler för användarnamn |
En algoritm för normalisering
- Step 1Trimma och lägg till ett schema
Ta bort blanksteg och lösa vinkelparenteser. Om indatan saknar schema, lägg till
https://först så attinstagram.com/natgeogår att tolka. - Step 2Tolka med en riktig URL-tolk
Använd
new URL()i JavaScript ellerurllib.parse.urlspliti Python, aldrig ett reguljärt uttryck över hela strängen. En tolk hanterar portar, användarinformation och kodade tecken, och stopparhttps://instagram.com@evil.com/natgeofrån att passera som Instagram. - Step 3Normalisera värden
Gör om den till gemener och ta bort ett inledande
www.,m.ellermobile.. Slå sedan upp den i en exakt lista över tillåtna värdar. Använd aldrigincludes("instagram.com"), som även matcharinstagram.com.evil.com. - Step 4Ta bort frågesträngen och fragmentet
Spårningsparametrar som
igsh,s,tochlangändrar aldrig vilken profil en URL pekar på. - Step 5Dela upp och avkoda sökvägen
Dela på
/, ta bort tomma segment (det tar bort avslutande snedstreck) och procentavkoda varje segment. Behandla felaktig kodning som ogiltig indata. - Step 6Dirigera per plattform
Tillämpa varje plattforms form: ett segment på Instagram och X, ett
@-segment på TikTok, och@handle,channel/UC...,user/nameellerc/namepå YouTube. Avvisa reserverade ord. - Step 7Validera handlet och gör om det till gemener
Kontrollera handlet mot plattformens teckenregler och gör sedan om det till gemener. Gör inte om YouTube-kanal-ID:n till gemener: de är skiftlägeskänsliga.
- Step 8Bygg den kanoniska URL:en
Bygg upp URL:en igen från delarna på en fast värd, så att varje likvärdig indata ger exakt samma sträng.
- Step 9Hantera kortlänkar för sig
Känn igen TikToks kortlänkar, följ omdirigeringen med en HTTP-förfrågan och kör den slutliga URL:en genom tolken igen. Håll det här utanför den rena funktionen så att tolkningen förblir snabb och testbar.
Koden i JavaScript och Python
Båda funktionerna returnerar samma objekt för samma indata: { platform, handle, canonicalUrl } för handle-adresser, { platform, channelId, canonicalUrl } för YouTube-kanal-ID:n, username eller customName för de två äldre YouTube-formerna, och null för allt som inte är en profiladress. Ingen av dem kräver något beroende.
JavaScript (Node 18+)
const HOSTS = {
"instagram.com": "instagram",
"tiktok.com": "tiktok",
"youtube.com": "youtube",
"x.com": "x",
"twitter.com": "x",
};
const IG_RESERVED = new Set(["p", "reel", "reels", "tv", "stories", "explore", "accounts", "direct"]);
const X_RESERVED = new Set([
"home", "explore", "search", "i", "settings", "notifications", "messages",
"compose", "intent", "hashtag", "login", "signup", "logout", "tos", "privacy",
]);
const IG_HANDLE = /^[a-z0-9._]{1,30}$/;
const TIKTOK_HANDLE = /^[a-z0-9._]{2,24}$/;
const X_HANDLE = /^[a-z0-9_]{1,15}$/;
const YT_HANDLE = /^[\p{L}\p{M}\p{N}._\-·]{1,30}$/u;
const YT_CHANNEL_ID = /^UC[A-Za-z0-9_-]{22}$/;
const YT_LEGACY_NAME = /^[A-Za-z0-9._-]{1,100}$/;
export function parseProfileUrl(input) {
if (typeof input !== "string") return null;
let raw = input.trim().replace(/^<|>$/g, "");
if (!raw) return null;
if (!/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) raw = "https://" + raw;
let url;
try {
url = new URL(raw);
} catch {
return null;
}
if (url.protocol !== "https:" && url.protocol !== "http:") return null;
const host = url.hostname.toLowerCase().replace(/^(www|m|mobile)\./, "");
const platform = HOSTS[host];
if (!platform) return null;
let segments;
try {
segments = url.pathname.split("/").filter(Boolean).map(decodeURIComponent);
} catch {
return null; // malformed percent-encoding
}
const [first = "", second] = segments;
if (platform === "instagram") {
const handle = first.toLowerCase();
if (segments.length !== 1 || IG_RESERVED.has(handle) || !IG_HANDLE.test(handle)) return null;
return { platform, handle, canonicalUrl: `https://www.instagram.com/${handle}/` };
}
if (platform === "tiktok") {
if (segments.length !== 1 || !first.startsWith("@")) return null;
const handle = first.slice(1).toLowerCase();
if (!TIKTOK_HANDLE.test(handle) || handle.endsWith(".")) return null;
return { platform, handle, canonicalUrl: `https://www.tiktok.com/@${handle}` };
}
if (platform === "x") {
const handle = first.toLowerCase();
if (segments.length !== 1 || X_RESERVED.has(handle) || !X_HANDLE.test(handle)) return null;
return { platform, handle, canonicalUrl: `https://x.com/${handle}` };
}
// YouTube: /@handle[/tab], /channel/UC...[/tab], /user/name, /c/name
if (first.startsWith("@")) {
const handle = first.slice(1).toLowerCase();
if (!YT_HANDLE.test(handle) || /^[._\-·]|[._\-·]$/.test(handle)) return null;
return { platform, handle, canonicalUrl: `https://www.youtube.com/@${encodeURIComponent(handle)}` };
}
if (first === "channel" && second && YT_CHANNEL_ID.test(second)) {
return { platform, channelId: second, canonicalUrl: `https://www.youtube.com/channel/${second}` };
}
if ((first === "user" || first === "c") && second && segments.length === 2 && YT_LEGACY_NAME.test(second)) {
const key = first === "user" ? "username" : "customName";
return { platform, [key]: second, canonicalUrl: `https://www.youtube.com/${first}/${second}` };
}
return null; // videos, shorts, playlists, search and anything else
}
const SHORT_HOSTS = new Set(["vm.tiktok.com", "vt.tiktok.com"]);
export function isShortLink(input) {
try {
const url = new URL(/^https?:\/\//i.test(input) ? input : "https://" + input);
const host = url.hostname.toLowerCase();
return SHORT_HOSTS.has(host) || (host.replace(/^www\./, "") === "tiktok.com" && url.pathname.startsWith("/t/"));
} catch {
return false;
}
}
export async function resolveShortLink(input) {
const res = await fetch(/^https?:\/\//i.test(input) ? input : "https://" + input, {
redirect: "follow",
signal: AbortSignal.timeout(10_000),
});
await res.body?.cancel();
return res.url; // the final URL after every redirect
}resolveShortLink använder den inbyggda fetch, som följer omdirigeringar och exponerar den slutliga adressen som res.url. Anropa parseProfileUrl(await resolveShortLink(link)) när isShortLink(link) är sant. En kortlänk kan också leda till en video i stället för en profil, och då returnerar tolken korrekt null.
Python 3
import re
import unicodedata
import urllib.request
from urllib.parse import quote, unquote, urlsplit
HOSTS = {
"instagram.com": "instagram",
"tiktok.com": "tiktok",
"youtube.com": "youtube",
"x.com": "x",
"twitter.com": "x",
}
IG_RESERVED = {"p", "reel", "reels", "tv", "stories", "explore", "accounts", "direct"}
X_RESERVED = {
"home", "explore", "search", "i", "settings", "notifications", "messages",
"compose", "intent", "hashtag", "login", "signup", "logout", "tos", "privacy",
}
IG_HANDLE = re.compile(r"[a-z0-9._]{1,30}")
TIKTOK_HANDLE = re.compile(r"[a-z0-9._]{2,24}")
X_HANDLE = re.compile(r"[a-z0-9_]{1,15}")
YT_CHANNEL_ID = re.compile(r"UC[A-Za-z0-9_-]{22}")
YT_LEGACY_NAME = re.compile(r"[A-Za-z0-9._-]{1,100}")
YT_PUNCT = "._-·"
def _is_youtube_handle(handle):
if not 1 <= len(handle) <= 30 or handle[0] in YT_PUNCT or handle[-1] in YT_PUNCT:
return False
return all(
ch.isalnum() or ch in YT_PUNCT or unicodedata.category(ch).startswith("M")
for ch in handle
)
def parse_profile_url(value):
if not isinstance(value, str):
return None
raw = value.strip().strip("<>")
if not raw:
return None
if not re.match(r"^[a-z][a-z0-9+.-]*://", raw, re.I):
raw = "https://" + raw
try:
url = urlsplit(raw)
host = (url.hostname or "").lower()
except ValueError:
return None
if url.scheme.lower() not in ("http", "https"):
return None
host = re.sub(r"^(www|m|mobile)\.", "", host)
platform = HOSTS.get(host)
if not platform:
return None
try:
segments = [unquote(s, errors="strict") for s in url.path.split("/") if s]
except UnicodeDecodeError:
return None # malformed percent-encoding
first = segments[0] if segments else ""
second = segments[1] if len(segments) > 1 else None
if platform == "instagram":
handle = first.lower()
if len(segments) != 1 or handle in IG_RESERVED or not IG_HANDLE.fullmatch(handle):
return None
return {"platform": platform, "handle": handle,
"canonicalUrl": f"https://www.instagram.com/{handle}/"}
if platform == "tiktok":
if len(segments) != 1 or not first.startswith("@"):
return None
handle = first[1:].lower()
if not TIKTOK_HANDLE.fullmatch(handle) or handle.endswith("."):
return None
return {"platform": platform, "handle": handle,
"canonicalUrl": f"https://www.tiktok.com/@{handle}"}
if platform == "x":
handle = first.lower()
if len(segments) != 1 or handle in X_RESERVED or not X_HANDLE.fullmatch(handle):
return None
return {"platform": platform, "handle": handle, "canonicalUrl": f"https://x.com/{handle}"}
# YouTube: /@handle[/tab], /channel/UC...[/tab], /user/name, /c/name
if first.startswith("@"):
handle = first[1:].lower()
if not _is_youtube_handle(handle):
return None
return {"platform": platform, "handle": handle,
"canonicalUrl": f"https://www.youtube.com/@{quote(handle, safe='._-')}"}
if first == "channel" and second and YT_CHANNEL_ID.fullmatch(second):
return {"platform": platform, "channelId": second,
"canonicalUrl": f"https://www.youtube.com/channel/{second}"}
if first in ("user", "c") and second and len(segments) == 2 and YT_LEGACY_NAME.fullmatch(second):
key = "username" if first == "user" else "customName"
return {"platform": platform, key: second,
"canonicalUrl": f"https://www.youtube.com/{first}/{second}"}
return None # videos, shorts, playlists, search and anything else
SHORT_HOSTS = {"vm.tiktok.com", "vt.tiktok.com"}
def is_short_link(value):
url = urlsplit(value if re.match(r"^https?://", value, re.I) else "https://" + value)
host = (url.hostname or "").lower()
return host in SHORT_HOSTS or (
re.sub(r"^www\.", "", host) == "tiktok.com" and url.path.startswith("/t/")
)
def resolve_short_link(value, timeout=10):
if not re.match(r"^https?://", value, re.I):
value = "https://" + value
request = urllib.request.Request(value, headers={"User-Agent": "Mozilla/5.0"})
with urllib.request.urlopen(request, timeout=timeout) as response:
return response.geturl() # the final URL after every redirectPythons \w och str.isalnum() täcker Unicode-bokstäver och siffror men inte de kombinerande tecken som skriftsystem som devanagari använder. Därför accepterar YouTube-kontrollen även tecken i Unicode-kategorierna M.
Kantfall och tester
Varje rad nedan ingår i testsviten som båda implementationerna klarar.
| Indata | Utdata | Varför |
|---|---|---|
instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA== | instagram, natgeo, https://www.instagram.com/natgeo/ | Inget schema, blandat skiftläge, delningsparameter |
https://m.instagram.com/nat.geo_/#bio | instagram, nat.geo_ | Mobilvärd och fragment |
https://www.instagram.com/p/C9xYzAbCdEf/ | null | Ett inlägg, inte en profil |
https://www.instagram.com/stories/natgeo/1234567890/ | null | En story, trots att handlet finns i sökvägen |
tiktok.com/@Khaby.Lame/ | tiktok, khaby.lame, https://www.tiktok.com/@khaby.lame | Avslutande snedstreck och skiftläge |
https://www.tiktok.com/@khaby.lame/video/7106594312292453675 | null | En videoadress |
https://vm.tiktok.com/ZMabc123/ | null (följ omdirigeringen först) | Kortlänk utan handle |
https://m.youtube.com/@GoogleDevelopers/videos?app=desktop | youtube, googledevelopers | Mobilvärd, kanalflik, frågesträng |
https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/featured | youtube, channelId UC_x5XG1OV2P6uZZ5FSM9Ttw | Kanal-ID:t behåller sitt skiftläge |
https://www.youtube.com/c/GoogleDevelopers | youtube, customName GoogleDevelopers | Äldre anpassad URL, kräver ett uppslag för ID:t |
https://www.youtube.com/@%E3%83%86%E3%82%B9%E3%83%88 | youtube, handle テスト | Procentkodat Unicode-handle |
https://youtu.be/dQw4w9WgXcQ | null | En video, inte en kanal |
https://mobile.twitter.com/jack?s=21&t=abc | x, jack, https://x.com/jack | Gammal domän och delningsparametrar |
https://x.com/i/flow/login | null | App-rutt |
https://x.com/this_handle_is_too_long | null | Fler än 15 tecken |
https://instagram.com.evil.com/natgeo | null | Värd som ser likadan ut |
https://instagram.com@evil.com/natgeo | null | Trick med användarinformation, den riktiga värden är evil.com |
@natgeo | null | Ett handle utan URL har ingen plattform |
Ha testfallen i ditt repo och kör dem i CI. När en plattform lägger till en rutt eller en delningsparameter lägger du till en rad, och lösningen blir uppenbar.
import assert from "node:assert/strict";
import { parseProfileUrl } from "./parse.mjs";
const cases = [
["instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA==", { platform: "instagram", handle: "natgeo", canonicalUrl: "https://www.instagram.com/natgeo/" }],
["https://www.instagram.com/reel/C9xYzAbCdEf/", null],
["https://www.instagram.com/explore/", null],
["tiktok.com/@Khaby.Lame/", { platform: "tiktok", handle: "khaby.lame", canonicalUrl: "https://www.tiktok.com/@khaby.lame" }],
["https://www.tiktok.com/@khaby.lame/video/7106594312292453675", null],
["https://vm.tiktok.com/ZMabc123/", null],
["https://m.youtube.com/@GoogleDevelopers/videos", { platform: "youtube", handle: "googledevelopers", canonicalUrl: "https://www.youtube.com/@googledevelopers" }],
["https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/featured", { platform: "youtube", channelId: "UC_x5XG1OV2P6uZZ5FSM9Ttw", canonicalUrl: "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw" }],
["https://www.youtube.com/user/GoogleDevelopers", { platform: "youtube", username: "GoogleDevelopers", canonicalUrl: "https://www.youtube.com/user/GoogleDevelopers" }],
["https://youtu.be/dQw4w9WgXcQ", null],
["https://twitter.com/Jack/", { platform: "x", handle: "jack", canonicalUrl: "https://x.com/jack" }],
["https://mobile.twitter.com/jack?s=21", { platform: "x", handle: "jack", canonicalUrl: "https://x.com/jack" }],
["https://x.com/jack/status/20", null],
["https://x.com/i/flow/login", null],
["https://instagram.com.evil.com/natgeo", null],
];
for (const [input, expected] of cases) {
assert.deepEqual(parseProfileUrl(input), expected, input);
}
console.log(`${cases.length} cases passed`);from parse_profile import parse_profile_url
CASES = [
("instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA==", {"platform": "instagram", "handle": "natgeo", "canonicalUrl": "https://www.instagram.com/natgeo/"}),
("https://www.instagram.com/reel/C9xYzAbCdEf/", None),
("tiktok.com/@Khaby.Lame/", {"platform": "tiktok", "handle": "khaby.lame", "canonicalUrl": "https://www.tiktok.com/@khaby.lame"}),
("https://vm.tiktok.com/ZMabc123/", None),
("https://m.youtube.com/@GoogleDevelopers/videos", {"platform": "youtube", "handle": "googledevelopers", "canonicalUrl": "https://www.youtube.com/@googledevelopers"}),
("https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/featured", {"platform": "youtube", "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw", "canonicalUrl": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw"}),
("https://youtu.be/dQw4w9WgXcQ", None),
("https://twitter.com/Jack/", {"platform": "x", "handle": "jack", "canonicalUrl": "https://x.com/jack"}),
("https://x.com/i/flow/login", None),
("https://instagram.com.evil.com/natgeo", None),
]
for value, expected in CASES:
assert parse_profile_url(value) == expected, value
print(f"{len(CASES)} cases passed")Spara både rå indata och den kanoniska formen
Normalisering förlorar information med flit, och dina regler kommer att bli bättre med tiden. Spara båda värdena:
- `raw_url`: exakt det som användaren eller importen gav dig. Med det kan du köra en bättre tolk senare, och det är det du visar för användaren när hen redigerar sin profil.
- `platform` och `handle` eller `channel_id`: delarna, med ett unikt index på
(platform, handle). Det här är din nyckel för dubblettkontroll och joins. - `canonical_url`: den återuppbyggda URL:en, för visning och för anrop till plattformen.
- `parsed_at` och en version av tolken: så att du kan hitta rader som normaliserades med en äldre version av dina regler.
Handles är inte permanenta. Kreatörer byter namn på sina konton på alla plattformar, och ett handle du sparade förra året kan nu tillhöra någon annan. Där ett officiellt API ger dig ett stabilt ID, som ett YouTube-kanal-ID, spara det som långsiktig nyckel och behandla handlet som ett visningsvärde som du uppdaterar. Den kompletterande guiden om att få fram ett YouTube-kanal-ID från ett handle visar hur.
Från en profil till de andra
När en profiladress är normaliserad är nästa fråga oftast vilka andra konton som tillhör samma kreatör. sociallinks.dev är ett API som tar en profiladress från Instagram, TikTok, YouTube eller X och returnerar kreatörens konton på andra plattformar, med en konfidenspoäng och bevisen för varje matchning.
Vanliga frågor
Ska jag göra om handles till gemener innan jag sparar dem?
Ja, för uppslagsnyckeln. YouTube och X säger att handles inte är skiftlägeskänsliga, och TikTok leder @TikTok till samma konto som @tiktok. Instagram dokumenterar ingen regel för skiftläge, men användarnamn visas med gemener, så gemener är det säkra standardvalet. Behåll den ursprungliga stavningen i den råa URL:en om du vill visa den. Gör inte om YouTube-kanal-ID:n till gemener, eftersom de är skiftlägeskänsliga.
Kan jag plocka ut handlet ur en adress till ett inlägg eller en video?
För TikTok-videor (/@handle/video/id) och inlägg på X (/handle/status/id) är handlet i sökvägen upphovspersonen, så du kan plocka ut det om det är vad du vill. Adresser till inlägg och reels på Instagram (/p/ och /reel/) innehåller inte handlet. Funktionerna i den här guiden returnerar null för alla dessa eftersom de inte är profillänkar.
Hur hanterar jag vm.tiktok.com-länkar?
Kortlänkar innehåller bara en kod. Gör en HTTP-förfrågan, följ omdirigeringarna och tolka den slutliga URL:en. Gör det i ett separat steg med timeout och cache, eftersom det är ett nätverksanrop och koden kan gå ut.
Är twitter.com fortfarande en giltig profiladress?
Ja. Profiladresser på twitter.com omdirigerar till x.com, så behandla båda domänerna som plattformen X och spara x.com-formen som kanonisk.
Varför inte använda ett enda stort reguljärt uttryck?
Ett enda reguljärt uttryck över hela strängen är svårläst och lätt att lura med värdar som ser likadana ut, användarinformation eller kodade tecken. Tolka först URL:en med standardbiblioteket och använd sedan små reguljära uttryck bara på handlet.
Hur gör jag om en YouTube-adress med /c/ eller /user/ till ett kanal-ID?
Adresser med /user/<name> motsvarar filtret forUsername i YouTube Data API. Det finns inget API-filter för anpassade /c/-namn. Läs guiden om att få fram ett YouTube-kanal-ID från ett handle för båda fallen.