{"url_pattern":"^https?://(www\\.)?tiktok\\.com(/.*)?$","site_name":"tiktok","allowed_domains":["example.com","tiktok.com"],"tools":[{"name":"tiktok_explore","description":"Get trending TikTok videos from explore page","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of videos","default":20}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 20}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/explore\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const links = Array.from(document.querySelectorAll('a[href*=\"/video/\"]'));\n  const seen = new Set();\n  const results = [];\n  for (const a of links) {\n    const href = a.href;\n    if (seen.has(href)) continue;\n    seen.add(href);\n    const match = href.match(/@([^/]+)\\/video\\/(\\d+)/);\n    results.push({\n      rank: results.length + 1,\n      author: match ? match[1] : '',\n      views: a.textContent.trim() || '-',\n      url: href,\n    });\n    if (results.length >= limit) break;\n  }\n  return results;\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_following","description":"List accounts you follow on TikTok","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of accounts","default":20}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 20}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/following\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const links = Array.from(document.querySelectorAll('a[href*=\"/@\"]'))\n    .filter(function(a) {\n      const text = a.textContent.trim();\n      return text.length > 1 && text.length < 80 &&\n        !text.includes('Profile') && !text.includes('More') && !text.includes('Upload');\n    });\n\n  const seen = {};\n  const results = [];\n  for (const a of links) {\n    const match = a.href.match(/@([^/]+)/);\n    const username = match ? match[1] : '';\n    if (!username || seen[username]) continue;\n    seen[username] = true;\n    const raw = a.textContent.trim();\n    const name = raw.replace(username, '').replace('@', '').trim();\n    results.push({\n      index: results.length + 1,\n      username: username,\n      name: name || username,\n    });\n    if (results.length >= limit) break;\n  }\n  return results;\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_friends","description":"Get TikTok friend suggestions","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of suggestions","default":20}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 20}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/friends\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const links = Array.from(document.querySelectorAll('a[href*=\"/@\"]'))\n    .filter(function(a) {\n      const text = a.textContent.trim();\n      return text.length > 1 && text.length < 80 &&\n        !text.includes('Profile') && !text.includes('More') && !text.includes('Upload');\n    });\n\n  const seen = {};\n  const results = [];\n  for (const a of links) {\n    const match = a.href.match(/@([^/]+)/);\n    const username = match ? match[1] : '';\n    if (!username || seen[username]) continue;\n    seen[username] = true;\n    const raw = a.textContent.trim();\n    const hasFollow = raw.includes('Follow');\n    const name = raw.replace('Follow', '').replace(username, '').replace('@', '').trim();\n    results.push({\n      index: results.length + 1,\n      username: username,\n      name: name || username,\n    });\n    if (results.length >= limit) break;\n  }\n  return results;\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_live","description":"Browse live streams on TikTok","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of streams","default":10}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/live\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  // Sidebar live list has structured data\n  const items = document.querySelectorAll('[data-e2e=\"live-side-nav-item\"]');\n  const sidebar = Array.from(items).slice(0, limit).map(function(el, i) {\n    const nameEl = el.querySelector('[data-e2e=\"live-side-nav-name\"]');\n    const countEl = el.querySelector('[data-e2e=\"person-count\"]');\n    const link = el.querySelector('a');\n    return {\n      index: i + 1,\n      streamer: nameEl ? nameEl.textContent.trim() : '',\n      viewers: countEl ? countEl.textContent.trim() : '-',\n      url: link ? link.href : '',\n    };\n  });\n\n  if (sidebar.length > 0) return sidebar;\n\n  // Fallback: main content cards\n  const cards = document.querySelectorAll('[data-e2e=\"discover-list-live-card\"]');\n  return Array.from(cards).slice(0, limit).map(function(card, i) {\n    const text = card.textContent.trim().replace(/\\s+/g, ' ');\n    const link = card.querySelector('a[href*=\"/live\"]');\n    const viewerMatch = text.match(/(\\d[\\d,.]*)\\s*watching/);\n    return {\n      index: i + 1,\n      streamer: text.replace(/LIVE.*$/, '').trim().substring(0, 40),\n      viewers: viewerMatch ? viewerMatch[1] : '-',\n      url: link ? link.href : '',\n    };\n  });\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_profile","description":"Get TikTok user profile info","inputSchema":{"type":"object","properties":{"username":{"type":"string","description":"TikTok username (without @)"}},"required":["username"]},"handler":"(params) => {\n  const args = Object.assign({}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/explore\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((async () => {\n  const username = ((args.username));\n  const res = await fetch('https://www.tiktok.com/@' + encodeURIComponent(username), { credentials: 'include' });\n  if (!res.ok) throw new Error('User not found: ' + username);\n  const html = await res.text();\n  const idx = html.indexOf('__UNIVERSAL_DATA_FOR_REHYDRATION__');\n  if (idx === -1) throw new Error('Could not parse profile data');\n  const start = html.indexOf('>', idx) + 1;\n  const end = html.indexOf('</script>', start);\n  const data = JSON.parse(html.substring(start, end));\n  const ud = data['__DEFAULT_SCOPE__'] && data['__DEFAULT_SCOPE__']['webapp.user-detail'];\n  const u = ud && ud.userInfo && ud.userInfo.user;\n  const s = ud && ud.userInfo && ud.userInfo.stats;\n  if (!u) throw new Error('User not found: ' + username);\n  return [{\n    username: u.uniqueId || username,\n    name: u.nickname || '',\n    bio: (u.signature || '').replace(/\\n/g, ' ').substring(0, 120),\n    followers: s && s.followerCount || 0,\n    following: s && s.followingCount || 0,\n    likes: s && s.heartCount || 0,\n    videos: s && s.videoCount || 0,\n    verified: u.verified ? 'Yes' : 'No',\n  }];\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_search","description":"Search TikTok videos","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"limit":{"type":"number","description":"Number of results","default":10}},"required":["query"]},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.tiktok.com/explore\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((async () => {\n  const query = ((args.query));\n  const limit = (args.limit);\n  const res = await fetch('/api/search/general/full/?keyword=' + encodeURIComponent(query) + '&offset=0&count=' + limit + '&aid=1988', { credentials: 'include' });\n  if (!res.ok) throw new Error('Search failed: HTTP ' + res.status);\n  const data = await res.json();\n  const items = (data.data || []).filter(function(i) { return i.type === 1 && i.item; });\n  return items.slice(0, limit).map(function(i, idx) {\n    var v = i.item;\n    var a = v.author || {};\n    var s = v.stats || {};\n    return {\n      rank: idx + 1,\n      desc: (v.desc || '').replace(/\\n/g, ' ').substring(0, 100),\n      author: a.uniqueId || '',\n      url: (a.uniqueId && v.id) ? 'https://www.tiktok.com/@' + a.uniqueId + '/video/' + v.id : '',\n      plays: s.playCount || 0,\n      likes: s.diggCount || 0,\n      comments: s.commentCount || 0,\n      shares: s.shareCount || 0,\n    };\n  });\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"tiktok_user","description":"Get recent videos from a TikTok user","inputSchema":{"type":"object","properties":{"username":{"type":"string","description":"TikTok username (without @)"},"limit":{"type":"number","description":"Number of videos","default":10}},"required":["username"]},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(`https://www.tiktok.com/@${args.username}`);\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const username = ((args.username));\n  const links = Array.from(document.querySelectorAll('a[href*=\"/video/\"]'));\n  const seen = {};\n  const results = [];\n  for (const a of links) {\n    const href = a.href;\n    if (seen[href]) continue;\n    seen[href] = true;\n    results.push({\n      index: results.length + 1,\n      views: a.textContent.trim() || '-',\n      url: href,\n    });\n    if (results.length >= limit) break;\n  }\n  if (results.length === 0) throw new Error('No videos found for @' + username);\n  return results;\n})())());\n    }\n    return data;\n  })();\n}"}]}