# How do I search TikTok and YouTube by what happens in a video?

Search an index of moments instead of each app. UpRock's video_search takes a plain description, like "snorkeling with sea turtles", and returns up to ten short moments from public YouTube, TikTok and Instagram video, each with its start and end time and a link back to the original, so you land on the part that matches instead of the start of an hour-long video. It costs $1 per 1,000 searches.

Updated 25 Oct 2026. Web page: https://uprock.ai/video/search-video-by-what-happens

## On this page

- [What a moment search returns](#what-a-moment-search-returns)
- [Five searches we ran on 25 Oct 2026](#five-searches-we-ran-on-25-oct-2026)
- [Linking to the exact second](#linking-to-the-exact-second)
- [Searching from code](#searching-from-code)
- [Speed, filters and cost](#speed-filters-and-cost)
- [FAQ](#faq)
- [Other use cases to explore](#explore)
- [Related articles](#related)
- [References](#references)
- [Get started](#get-started)

## What a moment search returns

The thing you're looking for is often 30 seconds in the middle of a long video, and nobody says it out loud. A moment index cuts each video into short windows and keeps notes on each one: what's said, a model-written description of what happens, and the timestamps. A search compares your words with those notes by meaning and returns the windows, not just the video. The index holds notes on public videos, not copies of them, and every result points back to the original post.

UpRock's `video_search` tool, on the MCP server at `https://mcp.uprock.ai/mcp`, with your API key in an `Authorization: Bearer` header (clients that can't send headers can use `https://mcp.uprock.ai/<API_KEY>/mcp` instead), returns up to 10 results, best first. Each result has:

| Field | What it is |
|---|---|
| `url` | The original post on YouTube, TikTok or Instagram |
| `t0`, `t1` | Start and end of the moment, in seconds from the start of the video |
| `score` | How well the moment matches, for ranking within one search |
| `title` | The post's title as indexed (Instagram posts show "Video by" and the account name) |
| `transcript` | An excerpt of what's said in the moment; empty when nobody speaks |
| `source` | The platform: `youtube`, `tiktok` or `instagram` |
| `published_at` | When the video was published, in unix seconds |

Moments are windows of up to 30 seconds on a 25-second grid: every `t0` we saw was a multiple of 25. Three options shape the results. `unique_videos` (on by default) keeps only the best moment from each video, `published_after` and `published_before` (unix seconds) limit the publish dates, and `order_by_recency` sorts newest first, with relevance as the tiebreak.

## Five searches we ran on 25 Oct 2026

We ran each query once with the default settings and copied the top three results. Titles are trimmed, and each links to the moment; YouTube links start at the second.

### "walking through a night market with street food"

| Platform | Moment | Score | Title |
|---|---|---|---|
| YouTube | 10:00 to 10:30 | 0.708 | [First Time Trying Turkey's Famous Wet Burger in Taksim Square](https://www.youtube.com/watch?v=PGYkq8ybnWE&t=600s) |
| Instagram | 0:00 to 0:30 | 0.704 | [Video by lonelyplanet](https://www.instagram.com/reel/DXZlDWwkidw/) |
| YouTube | 50:00 to 50:30 | 0.687 | [Istanbul Street Food!! ULTIMATE TURKISH FOOD You Must-Try in Istanbul](https://www.youtube.com/watch?v=QoG1-v1xagU&t=3000s) |

The top ten held five YouTube moments, four Instagram and one TikTok. Two of these three sit 10 and 50 minutes into long food tours, and the first is narrated in Urdu.

### "snorkeling with sea turtles"

| Platform | Moment | Score | Title |
|---|---|---|---|
| YouTube | 7:05 to 7:35 | 0.749 | [$1 vs $1,000,000 Vacation!](https://www.youtube.com/watch?v=K7FjCmlWvuY&t=425s) |
| YouTube | 48:20 to 48:50 | 0.631 | [Morning News NOW Full Episode, June 17](https://www.youtube.com/watch?v=FqnW9X-DNwM&t=2900s) |
| Instagram | 0:00 to 0:24 | 0.609 | [Video by visitjapanau](https://www.instagram.com/reel/DL9qZb0IDv0/) |

Five YouTube and five Instagram moments. The second hit is a 30-second window 48 minutes into a full news episode, and neither of the two YouTube transcripts mentions turtles.

### "a cable car going up a mountain"

| Platform | Moment | Score | Title |
|---|---|---|---|
| YouTube | 8:45 to 9:15 | 0.712 | [Salzburg Vacation Travel Guide](https://www.youtube.com/watch?v=owI1QBHhbS0&t=525s) |
| Instagram | 0:00 to 0:27 | 0.702 | [Video by switzerland](https://www.instagram.com/reel/DPeGxMiil1Q/) |
| Instagram | 0:25 to 0:55 | 0.693 | [Video by karaandnate](https://www.instagram.com/reel/DYH0XU4yi49/) |

Eight Instagram moments and two YouTube. In the travel guide, the matching moment comes almost nine minutes in.

### "slicing a watermelon"

| Platform | Moment | Score | Title |
|---|---|---|---|
| YouTube | 1:15 to 1:45 | 0.712 | [Skin a Watermelon Party Trick](https://www.youtube.com/watch?v=Q6vVuj3iggE&t=75s) |
| YouTube | 0:50 to 1:20 | 0.672 | [Simple Watermelon Smoothie Hack](https://www.youtube.com/watch?v=IJ-h0SO8EUI&t=50s) |
| YouTube | 3:45 to 4:15 | 0.665 | [Nastya and new friendly family stories for children and their parents](https://www.youtube.com/watch?v=fmhaja6rpZw&t=225s) |

Eight YouTube moments and two TikTok, the first at number five. The third result is a near miss: a children's story in which a character has been turned into a watermelon. The words matched; the action didn't.

### "changing a bike tire"

| Platform | Moment | Score | Title |
|---|---|---|---|
| YouTube | 0:50 to 1:20 | 0.625 | [Man bikes from Pittsburgh to Dallas to watch his home team's World Cup match](https://www.youtube.com/watch?v=Rg2AtHdkC3A&t=50s) |
| TikTok | 0:25 to 0:55 | 0.618 | [the gremlins wanted a bike](https://www.tiktok.com/@kristy.sarah/video/7460637286728748331) |
| YouTube | 2:55 to 3:25 | 0.570 | [I Built 4 SECRET Rooms In ONE COLOR!](https://www.youtube.com/watch?v=IFYjvNt1fgY&t=175s) |

Judging by titles and transcripts, none of the top ten shows a tire being changed. A search only finds what has been indexed, and so far the index leans toward travel and food. How-to queries are worth a try, but check what comes back.

## Linking to the exact second

`t0` is the second to send people to. How you link to it depends on the platform:

| Platform | Link starts at a second? | How |
|---|---|---|
| YouTube | Yes | Add `t=` with the second, for example `https://www.youtube.com/watch?v=Q6vVuj3iggE&t=75s`. YouTube's [Share dialog](https://support.google.com/youtube/answer/57741) does the same when you tick "Start at", and embedded players take [`start` and `end`](https://developers.google.com/youtube/player_parameters) in seconds |
| TikTok | No documented parameter | Link to the post and print the time next to it |
| Instagram | No documented parameter | Link to the post and print the time next to it |

We couldn't find a start-time parameter in TikTok's or Instagram's documentation when we checked on 25 Oct 2026. It matters less than it sounds: of the 194 TikTok and Instagram moments in our 28 searches, 115 started at 0:00 and 180 in the first minute.

## Searching from code

Both versions call `video_search` over MCP, pass the filters, and print each moment with a link to it. Give them a query, and optionally a date to get only videos published since then, newest first.

### TypeScript (MCP)

```ts
// npm i @modelcontextprotocol/sdk   (Node 24+ runs .ts files directly)   env: UPROCK_API_KEY
// node moments.ts "snorkeling with sea turtles"              best moment per video
// node moments.ts "snorkeling with sea turtles" 2026-01-01   published since then, newest first
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

// One video_search result: a moment from t0 to t1 (seconds) in one public video.
type Moment = {
  url: string;
  t0: number;
  t1: number;
  score: number;
  title: string;
  transcript: string;
  source: string; // "youtube", "tiktok" or "instagram"
  published_at: number; // unix seconds
};

type SearchOptions = {
  since?: Date; // published_after
  newestFirst?: boolean; // order_by_recency
  everyMoment?: boolean; // unique_videos: false returns several moments per video
};

const uprock = new Client({ name: "video-moments", version: "1.0.0" });
await uprock.connect(
  new StreamableHTTPClientTransport(
    new URL("https://mcp.uprock.ai/mcp"),
    { requestInit: { headers: { Authorization: `Bearer ${process.env.UPROCK_API_KEY}` } } },
  ),
);

export async function searchMoments(query: string, opts: SearchOptions = {}) {
  const args: Record<string, unknown> = {
    query,
    unique_videos: !opts.everyMoment,
    order_by_recency: opts.newestFirst ?? false,
  };
  if (opts.since) args.published_after = Math.floor(opts.since.getTime() / 1000);
  const res = await uprock.callTool({ name: "video_search", arguments: args });
  const text =
    (res.content as { type: string; text?: string }[]).find((c) => c.type === "text")
      ?.text ?? "";
  if (res.isError) throw new Error(`UpRock: ${text}`);
  return (JSON.parse(text).results ?? []) as Moment[];
}

// YouTube links can start at a second. TikTok and Instagram document no such
// parameter, so their links open the post and the time is printed next to them.
export function linkToMoment(m: Moment) {
  const url = new URL(m.url);
  if (/(^|\.)youtube\.com$|^youtu\.be$/.test(url.hostname)) {
    url.searchParams.set("t", `${Math.floor(m.t0)}s`);
  }
  return url.toString();
}

function clock(seconds: number) {
  const s = Math.floor(seconds);
  const [h, m, sec] = [Math.floor(s / 3600), Math.floor((s % 3600) / 60), s % 60];
  const mmss = `${h ? String(m).padStart(2, "0") : m}:${String(sec).padStart(2, "0")}`;
  return h ? `${h}:${mmss}` : mmss;
}

const [query = "snorkeling with sea turtles", since] = process.argv.slice(2);
try {
  const moments = await searchMoments(
    query,
    since ? { since: new Date(since), newestFirst: true } : {},
  );
  for (const m of moments) {
    const when = `${clock(m.t0)}-${clock(m.t1)}`;
    console.log(
      `${m.score.toFixed(3)}  ${m.source.padEnd(9)} ${when.padEnd(13)} ${m.title.slice(0, 50)}`,
    );
    console.log(`       ${linkToMoment(m)}`);
  }
} finally {
  await uprock.close();
}
```

### Python (MCP SDK)

```python
# pip install "mcp>=2.3"   env: UPROCK_API_KEY
# python moments.py "snorkeling with sea turtles"              best moment per video
# python moments.py "snorkeling with sea turtles" 2026-01-01   published since then, newest first
import asyncio
import calendar
import json
import os
import sys
from datetime import date
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit

import httpx2
from mcp import Client
from mcp.client.streamable_http import streamable_http_client

# The key goes in an Authorization header, set on the HTTP client the MCP client uses.
UPROCK = "https://mcp.uprock.ai/mcp"
HEADERS = {"Authorization": f"Bearer {os.environ['UPROCK_API_KEY']}"}
YOUTUBE = {"youtube.com", "www.youtube.com", "m.youtube.com", "youtu.be"}


async def search_moments(
    client: Client,
    query: str,
    since: date | None = None,
    newest_first: bool = False,
    every_moment: bool = False,
) -> list[dict]:
    args = {
        "query": query,
        "unique_videos": not every_moment,  # False: several moments per video
        "order_by_recency": newest_first,
    }
    if since:
        args["published_after"] = calendar.timegm(since.timetuple())  # midnight UTC
    res = await client.call_tool("video_search", args)
    text = next((c.text for c in res.content if c.type == "text"), "")
    if res.is_error:
        raise RuntimeError(f"UpRock: {text}")
    return json.loads(text).get("results", [])


def link_to_moment(m: dict) -> str:
    """YouTube links can start at a second; TikTok and Instagram document no such
    parameter, so their links open the post and the time is printed next to them."""
    parts = urlsplit(m["url"])
    if parts.hostname in YOUTUBE:
        params = dict(parse_qsl(parts.query)) | {"t": f"{int(m['t0'])}s"}
        parts = parts._replace(query=urlencode(params))
    return urlunsplit(parts)


def clock(seconds: float) -> str:
    h, rest = divmod(int(seconds), 3600)
    m, s = divmod(rest, 60)
    return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"


async def main() -> None:
    query = sys.argv[1] if len(sys.argv) > 1 else "snorkeling with sea turtles"
    since = date.fromisoformat(sys.argv[2]) if len(sys.argv) > 2 else None
    async with (
        httpx2.AsyncClient(headers=HEADERS, timeout=httpx2.Timeout(30, read=300)) as http,
        Client(streamable_http_client(UPROCK, http_client=http)) as client,
    ):
        moments = await search_moments(client, query, since, newest_first=bool(since))
    for m in moments:
        when = f"{clock(m['t0'])}-{clock(m['t1'])}"
        print(f"{m['score']:.3f}  {m['source']:<9} {when:<13} {m['title'][:50]}")
        print(f"       {link_to_moment(m)}")


asyncio.run(main())
```

## Speed, filters and cost

- **Speed.** Searches with the default settings took 4.2 to 5.4 seconds (median 4.6) across 29 runs on 25 Oct 2026. With `unique_videos` off they took about 2.1 seconds and returned several moments from the same video, and a slightly different set: the night-market search lost its YouTube top hit.
- **Newest first.** `order_by_recency` sorts by publish date before relevance, so pair it with `published_after`. For "a cable car going up a mountain" since 1 Jan 2026, newest first, the top result was a news clip scoring 0.416; sorted by relevance, the same search led with a 0.694 match.
- **Cost.** $1 per 1,000 searches by card or USDC, $0.80 with UPT, prepaid. There's nothing to store and no plan.

Tested 25 Oct 2026 against the live UpRock MCP server: we extracted both code blocks from this page and ran them with "snorkeling with sea turtles", with and without a date (Node 25 with @modelcontextprotocol/sdk 1.32.2, Python 3.11 with mcp 2.3.0). Both printed ten moments, with YouTube links that start at the moment. We didn't open the links in a browser, so the start-time behavior follows YouTube's documentation. On 6 Nov 2026 we ran both code blocks again with an UpRock API key in an `Authorization` header, with and without a date.

## FAQ

### Does this search every video on YouTube, TikTok and Instagram?

No. It searches the public videos that have been indexed so far. In our 28 test searches on 25 Oct 2026, results came from YouTube, TikTok and Instagram; travel and food queries matched best, and a how-to query like "changing a bike tire" returned nothing on topic.

### Does UpRock keep copies of the videos?

No. The index holds notes on each video, such as transcripts, model-written descriptions of what happens and timestamps. Every result links to the original post, so people watch it where it was published.

### Can I link to the exact second on TikTok or Instagram?

We couldn't find a documented start-time parameter for either (checked 25 Oct 2026), so link to the post and show the time next to it. Most of their moments in our searches started in the first minute anyway. YouTube documents one; add t= with the second.

### What do t0, t1 and score mean?

t0 and t1 are the start and end of the moment in seconds from the start of the video. Moments are windows of up to 30 seconds on a 25-second grid. The score ranks results within one search and isn't a probability. On-topic top results scored about 0.6 to 0.75 in our runs, but an off-topic one scored 0.625.

### What does a search cost?

$1 per 1,000 searches by card or USDC, $0.80 with UPT, prepaid. Each search returns up to ten moments, and the filters don't change the price.

## Other use cases to explore

- [See where a transcript search would miss](https://uprock.ai/video/transcripts-vs-video-search#three-searches-where-the-transcript-wouldnt-have-matched): three searches whose best moments had no transcript, a speech-recognition artifact or speech in another language.
- [Give Claude Code video search](https://uprock.ai/integrations/claude-code): add UpRock's MCP server once and ask for the moment in a video from your terminal.
- [See a page as it looks in another country](https://uprock.ai/use-cases/page-from-another-country): load a URL on a real device in the country you choose.
- [The open video index](https://uprock.ai/video-semantic-search): how the shared index works, what's in it and what searching and indexing cost.

## Related articles

- [Is a transcript enough to search a video?](https://uprock.ai/video/transcripts-vs-video-search.md): Three real searches where the best moments had no transcript, a stock phrase or speech in another language, and when a transcript is enough and cheaper.
- [What does video AI cost in 2026? Indexing, search and storage](https://uprock.ai/video/video-understanding-costs.md): Indexing, search and storage prices for nine video AI services, checked on their own pages on 25 Oct 2026, and what 100 hours and 100,000 searches cost on each.
- [Can AI watch videos? Video understanding options for agents](https://uprock.ai/video/give-your-agent-eyes.md): A decision table for giving an agent video, from captions to a model that watches one video, a private index or a shared public index, with a tested function.
- [Video use cases: all articles](https://uprock.ai/video.md)

## References

1. [UpRock, everything in one file (MCP server, tools and prices)](https://uprock.ai/llms-full.txt), checked 25 Oct 2026
2. [UpRock, the open video index](https://uprock.ai/video-semantic-search), checked 25 Oct 2026
3. [YouTube Help, Share videos and channels ("Start at")](https://support.google.com/youtube/answer/57741), checked 25 Oct 2026
4. [YouTube IFrame Player API, player parameters (start and end)](https://developers.google.com/youtube/player_parameters), checked 25 Oct 2026

## Get started

Get an API key: https://uprock.ai/app/api-keys

Paste this into your agent:

```text
Set up UpRock for me: read https://uprock.ai/agents.md, connect the UpRock MCP server, and run one test crawl. Tell me what it costs before you spend anything.
```

Setup for every client (MCP, skill, CLI): https://uprock.ai/agents.md
