> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tornadoapi.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Is Short

> Detect whether a YouTube URL is a Short (vertical) or a regular video

## Overview

Classify a YouTube URL as a **Short** (vertical) or a regular **video** by inspecting the actual video dimensions. No download is performed.

This is more reliable than checking the URL pattern: a URL of the form `youtube.com/watch?v=...` can still be a Short in disguise (and vice versa). Only the real video dimensions tell the truth.

## How the classification works

* `is_short = height > width` on the best available video format
* `video_type` is `"live"` when the URL is a live stream, otherwise `"short"` when vertical, otherwise `"video"`
* `duration_seconds` is returned for context but does **not** affect the decision

## Header Parameters

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication
</ParamField>

## Request

<ParamField body="url" type="string" required>
  The YouTube URL to classify. Accepts every YouTube URL form: `watch?v=`, `youtu.be/`, `/shorts/`, `/embed/`. URLs from other platforms return `400`.
</ParamField>

## Response

<ResponseField name="is_short" type="boolean">
  `true` when the video is vertical (height greater than width).
</ResponseField>

<ResponseField name="video_type" type="string">
  One of `"short"`, `"video"`, or `"live"`.
</ResponseField>

<ResponseField name="width" type="integer">
  Width in pixels of the best available video format. May be `null` if no video-bearing format is exposed.
</ResponseField>

<ResponseField name="height" type="integer">
  Height in pixels of the best available video format. May be `null` if no video-bearing format is exposed.
</ResponseField>

<ResponseField name="aspect_ratio" type="number">
  `height / width`. Values greater than `1.0` mean vertical. May be `null` when dimensions are missing.
</ResponseField>

<ResponseField name="duration_seconds" type="integer">
  Total video duration in seconds. Informational only — not used in the classification.
</ResponseField>

## Examples

<CodeGroup>
  ```bash Detect a Short theme={null}
  curl -X POST "https://api.tornadoapi.io/is-short" \
    -H "x-api-key: sk_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://www.youtube.com/shorts/SXHMnicI6Pg"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.tornadoapi.io/is-short', {
    method: 'POST',
    headers: {
      'x-api-key': 'sk_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      url: 'https://www.youtube.com/watch?v=gUmlkXlhZo8'
    })
  });

  const result = await response.json();
  if (result.is_short) {
    console.log(`Short: ${result.width}x${result.height}, ${result.duration_seconds}s`);
  } else {
    console.log(`Regular video: ${result.video_type}`);
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.tornadoapi.io/is-short',
      headers={'x-api-key': 'sk_your_api_key'},
      json={'url': 'https://www.youtube.com/watch?v=gUmlkXlhZo8'}
  )

  result = response.json()
  print(f"Type: {result['video_type']}")
  print(f"Dimensions: {result['width']}x{result['height']}")
  print(f"Aspect ratio: {result['aspect_ratio']}")
  ```
</CodeGroup>

## Success Response

<ResponseExample>
  ```json 200 — Short theme={null}
  {
    "is_short": true,
    "video_type": "short",
    "width": 1080,
    "height": 1920,
    "aspect_ratio": 1.778,
    "duration_seconds": 33
  }
  ```

  ```json 200 — Regular video theme={null}
  {
    "is_short": false,
    "video_type": "video",
    "width": 1920,
    "height": 1080,
    "aspect_ratio": 0.5625,
    "duration_seconds": 213
  }
  ```

  ```json 200 — Live stream theme={null}
  {
    "is_short": false,
    "video_type": "live",
    "width": 1920,
    "height": 1080,
    "aspect_ratio": 0.5625,
    "duration_seconds": 0
  }
  ```
</ResponseExample>

## Error Responses

<ResponseExample>
  ```json 400 Bad Request — Not a YouTube URL theme={null}
  {
    "error": "Not a YouTube URL"
  }
  ```

  ```json 400 Bad Request — Video unavailable theme={null}
  {
    "error": "Video is private"
  }
  ```

  ```json 401 Unauthorized — Missing key theme={null}
  {
    "error": "Missing API key"
  }
  ```

  ```json 401 Unauthorized — Invalid key theme={null}
  {
    "error": "Invalid API Key"
  }
  ```

  ```json 502 Bad Gateway — Upstream failure theme={null}
  {
    "error": "Temporary YouTube error, please retry"
  }
  ```
</ResponseExample>

The 400 response covers two cases: the URL is not a recognised YouTube URL, or the video exists but is permanently unavailable (private, deleted, region-blocked, channel terminated).

The 401 response covers two cases: no `x-api-key` header was sent, or the key is invalid / revoked.

The 502 response means a transient upstream issue (proxy hiccup, YouTube error). Retry after a short delay.

## Use Cases

### Conditional routing

Pick a different quality preset, container, or storage folder based on whether the video is a Short.

### Pre-filtering a batch

When ingesting a creator's catalog, separate Shorts from full videos before queueing downloads.

### UI hints

Show a different player or thumbnail aspect ratio in your front-end as soon as the URL is pasted.

## Notes

* **Latency**: typically 2–3 seconds.
* **No server-side cache**: if you call the endpoint repeatedly for the same URL, consider caching the response on your side.
* **No download**: only video information is fetched; storage and bandwidth are not charged for this call.
