sociallinks.dev

בלוג / מדריך למפתחים

איך לפרק ולנרמל כתובות פרופיל ברשתות חברתיות (Instagram, TikTok, YouTube, X)

יוצרים מדביקים את קישורי הפרופיל שלהם בכל צורה אפשרית: עם www ובלי, מהאפליקציה בנייד עם פרמטרי מעקב, כקישורים מקוצרים, ככתובות twitter.com ישנות, או כקישור לפוסט במקום לפרופיל. אם המוצר שלכם שומר את המחרוזות כפי שהן מגיעות, אותו יוצר מופיע שלוש פעמים והצירופים (joins) שלכם מחטיאים בשקט. המדריך הזה מראה איך להפוך כל כתובת פרופיל של Instagram, TikTok, YouTube או X לפלטפורמה, לשם משתמש או מזהה ערוץ, ולכתובת קנונית אחת, עם קוד בדוק ב-JavaScript וב-Python.

למה חשוב לנרמל כתובות פרופיל

כתובת פרופיל היא מזהה, ומזהים עובדים רק כשכותבים אותם בדרך אחת. https://www.instagram.com/natgeo/, instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA== ו-https://m.instagram.com/natgeo מצביעים כולם על אותו חשבון, אבל כמחרוזות הם שלושה ערכים שונים.

המטרה היא פונקציה קטנה וקפדנית: היא מקבלת את מה שמשתמשים באמת מדביקים, מחזירה תוצאה מנורמלת לכתובות פרופיל אמיתיות, ומחזירה null לכל השאר.

צורות הכתובות שתפגשו

הצורות שבהמשך נבדקו מול האתרים החיים באוקטובר 2026. פלטפורמות משנות את הניתוב שלהן בלי הודעה, אז התייחסו לזה כתמונת מצב ושמרו על מקרי הבדיקה שלכם מעודכנים.

Instagram

TikTok

YouTube

X (לשעבר Twitter)

כללי התווים בשם משתמש לפי פלטפורמה

אימות שם המשתמש תופס שגיאות הקלדה ורוב הנתיבים שאינם פרופיל. השתמשו בכללים של הפלטפורמות עצמן היכן שהן מפרסמות אותם, והשאירו את הבדיקות רופפות היכן שלא, כדי שלעולם לא תדחו חשבון אמיתי.

פלטפורמהתווים מותריםאורךרישיותמקור
Instagramאותיות, ספרות, נקודות, קווים תחתונים30 מצוטט בהרבה מקומות; לא נמצא בדפי העזרה של Instagramהתייחסו כלא רגיש לרישיות; שמרו באותיות קטנותמרכז העזרה של Instagram מזכיר נקודות, ספרות וקווים תחתונים
TikTokאותיות, ספרות, קווים תחתונים, נקודות; לא יכול להסתיים בנקודה2 עד 24לא רגיש לרישיות בכתובות (@TikTok מוביל ל-tiktok)התמיכה של TikTok, שינוי שם המשתמש
YouTubeאותיות או ספרות משפות נתמכות, ועוד קווים תחתונים, מקפים, נקודות ונקודות אמצעיות לטיניות (לא בהתחלה או בסוף)3 עד 30 ברוב מערכות הכתב; מגבלות קצרות יותר לסינית, לקוריאנית ולכמה מערכות כתב אחרותלא רגיש לרישיותהעזרה של YouTube, הנחיות לשמות משתמש
Xאותיות, ספרות וקווים תחתוניםעד 15; שמות משתמש חדשים חייבים להיות ארוכים מ-4, אבל קיימים שמות קצרים ישניםלא רגיש לרישיות (x.com/JACK מנורמל ל-x.com/jack)מרכז העזרה של X, כללי שם משתמש

אלגוריתם נרמול

  1. Step 1חיתוך והוספת סכמה

    הסירו רווחים וסוגריים זוויתיים מיותרים. אם לקלט אין סכמה, הוסיפו https:// בהתחלה כדי ש-instagram.com/natgeo יפורק.

  2. Step 2פרקו עם מפרק URL אמיתי

    השתמשו ב-new URL() ב-JavaScript או ב-urllib.parse.urlsplit ב-Python, ולעולם לא בביטוי רגולרי על כל המחרוזת. מפרק מטפל בפורטים, בפרטי משתמש ובתווים מקודדים, ומונע מ-https://instagram.com@evil.com/natgeo לעבור כ-Instagram.

  3. Step 3נרמלו את השרת

    המירו לאותיות קטנות והסירו www., m. או mobile. אחד בהתחלה. אחר כך חפשו אותו ברשימת היתרים מדויקת של שרתים. לעולם אל תשתמשו ב-includes("instagram.com"), שתואם גם ל-instagram.com.evil.com.

  4. Step 4הסירו את מחרוזת השאילתה והפרגמנט

    פרמטרי מעקב כמו igsh, s, t ו-lang אף פעם לא משנים על איזה פרופיל כתובת מצביעה.

  5. Step 5פצלו ופענחו את הנתיב

    פצלו לפי /, הסירו מקטעים ריקים (זה מסיר לוכסנים בסוף) ופענחו כל אחד מקידוד אחוזים. התייחסו לקידוד פגום כקלט לא תקין.

  6. Step 6נתבו לפי פלטפורמה

    החילו את הצורה של כל פלטפורמה: מקטע אחד ב-Instagram וב-X, מקטע עם @ ב-TikTok, ו-@handle, channel/UC..., user/name או c/name ב-YouTube. דחו מילים שמורות.

  7. Step 7אמתו את שם המשתמש והמירו לאותיות קטנות

    בדקו את שם המשתמש מול כללי התווים של הפלטפורמה, ואז המירו לאותיות קטנות. אל תמירו מזהי ערוץ של YouTube לאותיות קטנות: הם רגישים לרישיות.

  8. Step 8בנו את הכתובת הקנונית

    בנו מחדש את הכתובת מהחלקים על שרת קבוע אחד, כך שכל קלט שקול ייצר בדיוק את אותה מחרוזת.

  9. Step 9טפלו בקישורים מקוצרים בנפרד

    זהו קישורים מקוצרים של TikTok, עקבו אחרי ההפניה בבקשת HTTP, והעבירו את הכתובת הסופית שוב דרך המפרק. השאירו את זה מחוץ לפונקציה הטהורה כדי שהפירוק יישאר מהיר וניתן לבדיקה.

הקוד ב-JavaScript וב-Python

שתי הפונקציות מחזירות את אותם אובייקטים לאותו קלט: { platform, handle, canonicalUrl } לכתובות שם משתמש, { platform, channelId, canonicalUrl } למזהי ערוץ של YouTube, username או customName לשתי הצורות הישנות של YouTube, ו-null לכל מה שאינו כתובת פרופיל. אף אחת מהן לא צריכה תלות חיצונית.

JavaScript (Node 18 ומעלה)

Node.js

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 משתמשת ב-fetch המובנה, שעוקב אחרי הפניות וחושף את הכתובת הסופית כ-res.url. קראו ל-parseProfileUrl(await resolveShortLink(link)) כש-isShortLink(link) מחזיר אמת. קישור מקוצר יכול להוביל גם לסרטון ולא לפרופיל, ואז המפרק מחזיר null כמו שצריך.

Python 3

Python

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 redirect

\w ו-str.isalnum() ב-Python מכסים אותיות וספרות של Unicode, אבל לא את הסימנים המצטרפים שמשמשים מערכות כתב כמו דוונאגרי, ולכן בדיקת YouTube מקבלת גם תווים בקטגוריות M של Unicode.

מקרי קצה ובדיקות

כל שורה בהמשך היא חלק מחבילת הבדיקות ששני המימושים עוברים.

קלטפלטלמה
instagram.com/NatGeo?igsh=MWQ1ZGUxMzBkMA==instagram, natgeo, https://www.instagram.com/natgeo/בלי סכמה, רישיות מעורבת, פרמטר שיתוף
https://m.instagram.com/nat.geo_/#bioinstagram, nat.geo_שרת נייד ופרגמנט
https://www.instagram.com/p/C9xYzAbCdEf/nullפוסט, לא פרופיל
https://www.instagram.com/stories/natgeo/1234567890/nullסטורי, למרות ששם המשתמש בנתיב
tiktok.com/@Khaby.Lame/tiktok, khaby.lame, https://www.tiktok.com/@khaby.lameלוכסן בסוף ורישיות
https://www.tiktok.com/@khaby.lame/video/7106594312292453675nullכתובת של סרטון
https://vm.tiktok.com/ZMabc123/null (קודם עקבו אחרי ההפניה)קישור מקוצר בלי שם משתמש
https://m.youtube.com/@GoogleDevelopers/videos?app=desktopyoutube, googledevelopersשרת נייד, לשונית ערוץ, שאילתה
https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/featuredyoutube, channelId UC_x5XG1OV2P6uZZ5FSM9Ttwמזהה הערוץ שומר על הרישיות שלו
https://www.youtube.com/c/GoogleDevelopersyoutube, customName GoogleDevelopersכתובת מותאמת ישנה; צריך חיפוש כדי לקבל את המזהה
https://www.youtube.com/@%E3%83%86%E3%82%B9%E3%83%88youtube, handle テストשם משתמש Unicode בקידוד אחוזים
https://youtu.be/dQw4w9WgXcQnullסרטון, לא ערוץ
https://mobile.twitter.com/jack?s=21&t=abcx, jack, https://x.com/jackדומיין ישן ופרמטרי שיתוף
https://x.com/i/flow/loginnullנתיב אפליקציה
https://x.com/this_handle_is_too_longnullיותר מ-15 תווים
https://instagram.com.evil.com/natgeonullשרת מתחזה
https://instagram.com@evil.com/natgeonullתעלול של פרטי משתמש; השרת האמיתי הוא evil.com
@natgeonullלשם משתמש בלבד אין פלטפורמה

שמרו את המקרים במאגר הקוד והריצו אותם ב-CI. כשפלטפורמה מוסיפה נתיב או פרמטר שיתוף, אתם מוסיפים שורה אחת והתיקון ברור.

בדיקה ב-Node.js

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`);

בדיקה ב-Python

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")

שמרו את הקלט הגולמי ואת הצורה הקנונית

נרמול מאבד מידע מעצם הגדרתו, והכללים שלכם ישתפרו עם הזמן. שמרו את שני הערכים:

שמות משתמש אינם קבועים. יוצרים משנים שמות חשבונות בכל פלטפורמה, ושם משתמש ששמרתם בשנה שעברה עשוי להיות שייך עכשיו למישהו אחר. היכן ש-API רשמי נותן מזהה יציב, כמו מזהה ערוץ YouTube, שמרו אותו כמפתח לטווח ארוך והתייחסו לשם המשתמש כערך תצוגה שאתם מרעננים. המדריך המשלים על קבלת מזהה ערוץ YouTube משם משתמש מראה איך.

מפרופיל אחד לאחרים

אחרי שכתובת פרופיל מנורמלת, השאלה הבאה היא בדרך כלל אילו חשבונות אחרים שייכים לאותו יוצר. sociallinks.dev הוא API שמקבל כתובת פרופיל אחת של Instagram, TikTok, YouTube או X ומחזיר את החשבונות של היוצר בפלטפורמות אחרות, עם ציון ביטחון והראיות לכל התאמה.

שאלות נפוצות

האם להמיר שמות משתמש לאותיות קטנות לפני שמירה?

כן, למפתח החיפוש. YouTube ו-X אומרות ששמות משתמש לא רגישים לרישיות, ו-TikTok מובילה את @TikTok לאותו חשבון כמו @tiktok. Instagram לא מתעדת כלל רישיות, אבל שמות משתמש מוצגים באותיות קטנות, אז המרה לאותיות קטנות היא ברירת המחדל הבטוחה. שמרו את הרישיות המקורית בכתובת הגולמית אם אתם רוצים להציג אותה. אל תמירו מזהי ערוץ של YouTube, שהם רגישים לרישיות.

אפשר לחלץ את שם המשתמש מכתובת של פוסט או סרטון?

בסרטוני TikTok (/@handle/video/id) ובפוסטים ב-X (/handle/status/id) שם המשתמש בנתיב הוא של הכותב, אז אפשר לחלץ אותו אם זה מה שאתם רוצים. כתובות של פוסטים ו-Reels ב-Instagram (/p/ ו-/reel/) לא כוללות את שם המשתמש. הפונקציות במדריך הזה מחזירות null לכולן, כי הן אינן קישורי פרופיל.

איך מטפלים בקישורי vm.tiktok.com?

קישורים מקוצרים מכילים רק קוד. שלחו בקשת HTTP, עקבו אחרי ההפניות ופרקו את הכתובת הסופית. עשו את זה בשלב נפרד עם זמן קצוב ומטמון, כי זו קריאת רשת והקוד יכול לפוג.

האם twitter.com הוא עדיין כתובת פרופיל תקפה?

כן. כתובות פרופיל של twitter.com מפנות ל-x.com, אז התייחסו לשני הדומיינים כפלטפורמת X ושמרו את צורת x.com כקנונית.

למה לא להשתמש בביטוי רגולרי אחד גדול?

ביטוי רגולרי אחד על כל המחרוזת קשה לקריאה וקל להטעות אותו עם שרתים מתחזים, פרטי משתמש או תווים מקודדים. פרקו קודם את הכתובת עם הספרייה הסטנדרטית, ואז השתמשו בביטויים רגולריים קטנים על שם המשתמש בלבד.

איך הופכים כתובת /c/ או /user/ של YouTube למזהה ערוץ?

כתובות /user/<name> ממופות למסנן forUsername של YouTube Data API. אין מסנן API לשמות מותאמים של /c/. ראו את המדריך על קבלת מזהה ערוץ YouTube משם משתמש לשני המקרים.

מצאו את החשבונות של יוצר