Why Video.js captions are not showing
TL;DR — Fix Video.js captions that do not show by checking WebVTT format, track configuration, file URLs, MIME type, and CORS.
Related tool
Video.js Subtitle Converter
Video.js caption problems usually come from WebVTT file issues or player configuration. This guide walks through the most common causes and how to fix them systematically.
Quick answer
Use WebVTT for Video.js captions. Validate the VTT file, confirm the file URL loads, and check the track configuration in your Video.js setup.
If your source file is SRT or ASS, convert it with the Video.js Subtitle Converter.
Why Video.js captions fail to display
Video.js is one of the most popular HTML5 video players, but caption issues are common. The player expects WebVTT format and requires proper server configuration. When captions don’t show, the problem usually falls into one of these categories:
- File format issues - Using SRT instead of VTT, or malformed WebVTT syntax
- Server configuration - Wrong MIME type or CORS blocking the caption file
- Player setup - Incorrect track configuration or disabled captions
- Path problems - Broken URLs or incorrect file paths after deployment
Understanding which category your issue falls into helps you fix it faster.
What to check
Check these in order:
- the caption file is valid WebVTT
- the VTT URL is correct
- the server returns the file successfully
- the server uses a suitable VTT content type
- CORS allows the player page to fetch captions
- the track is enabled in the player UI
Step-by-step workflow
1. Verify you’re using WebVTT format
Video.js requires WebVTT (.vtt) files for captions. SRT files won’t work directly.
Check your file:
- Open the caption file in a text editor
- The first line must be exactly
WEBVTT - Timestamps use dots, not commas:
00:00:01.000not00:00:01,000
If you have an SRT file:
- Use the Video.js Subtitle Converter to convert it
- The converter adds the WEBVTT header and fixes timestamp format
- Download the converted VTT file
2. Validate the VTT file structure
Even if your file has the WEBVTT header, syntax errors can prevent captions from displaying.
Common VTT syntax errors:
- Missing blank line after
WEBVTT - Cue identifiers that conflict with timestamps
- Malformed timestamp format
- Missing
-->separator between start and end times
How to validate:
- Use the WebVTT Validator
- Upload or paste your VTT file
- Fix any reported errors before testing in Video.js
3. Test the caption file URL directly
Before debugging the player, confirm the caption file is accessible.
Steps:
- Copy the caption file URL from your Video.js track configuration
- Paste it directly into your browser address bar
- Press Enter
What you should see:
- The VTT file content displays as plain text
- The first line shows
WEBVTT
If you see an error:
- 404 Not Found → The file path is wrong or the file wasn’t uploaded
- 403 Forbidden → Check file permissions on your server
- CORS error → See step 5 below
4. Verify the server MIME type
Browsers expect WebVTT files to be served with the correct content type.
Correct MIME types (any of these work):
text/vtttext/plainapplication/octet-stream
How to check:
- Open browser DevTools (F12)
- Go to the Network tab
- Reload your page
- Find the VTT file request
- Check the
Content-Typeresponse header
If the MIME type is wrong:
- Add this to your
.htaccess(Apache):AddType text/vtt .vtt - Or configure your CDN/hosting to serve
.vttfiles withtext/vtt
5. Check CORS configuration
If your caption file is hosted on a different domain than your player page, CORS must allow cross-origin requests.
Symptoms of CORS issues:
- Console error: “Access to fetch at ’…’ has been blocked by CORS policy”
- The VTT file loads when you open it directly, but not in the player
How to fix: Add this header to your caption file server:
Access-Control-Allow-Origin: *
Or restrict it to your player domain:
Access-Control-Allow-Origin: https://yourdomain.com
For Apache (.htaccess):
<FilesMatch "\.(vtt)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
For Nginx:
location ~* \.(vtt)$ {
add_header Access-Control-Allow-Origin *;
}
6. Review Video.js track configuration
Even with a valid VTT file, incorrect player setup can hide captions.
Check your HTML:
<video id="my-video" class="video-js" controls>
<source src="video.mp4" type="video/mp4">
<track kind="captions"
src="captions.vtt"
srclang="en"
label="English"
default>
</video>
Key attributes:
kind="captions"orkind="subtitles"(both work)srcmust point to a valid VTT file URLsrclangshould match the caption language (e.g.,en,es,fr)labelis what users see in the caption menudefaultmakes captions show automatically (optional)
JavaScript configuration:
var player = videojs('my-video');
player.addRemoteTextTrack({
kind: 'captions',
src: 'captions.vtt',
srclang: 'en',
label: 'English',
default: true
}, false);
7. Enable captions in the player UI
Even with everything configured correctly, captions might be disabled in the player.
How to enable:
- Click the CC (closed captions) button in the Video.js player controls
- Select your caption track from the menu
- Captions should appear immediately
If the CC button is missing: Check that your Video.js initialization includes controls:
var player = videojs('my-video', {
controls: true,
textTrackSettings: true
});
8. Clear browser cache and test
Browsers aggressively cache VTT files. After fixing issues, you might still see the old broken version.
Steps:
- Open DevTools (F12)
- Right-click the refresh button
- Select “Empty Cache and Hard Reload”
- Or use Ctrl+Shift+R (Windows) / Cmd+Shift+R (Mac)
Common mistakes
Using SRT directly
Video.js caption workflows should use WebVTT for browser playback. SRT files use a different timestamp format (commas instead of dots) and lack the required WEBVTT header.
Why this fails:
- Video.js expects
00:00:01.000but SRT uses00:00:01,000 - Browsers won’t parse the file without the
WEBVTTheader - The player silently fails with no error message
Solution: Always convert SRT to VTT before using with Video.js. Use the SRT to VTT Converter.
Debugging JavaScript before validating captions
Malformed VTT can look like a player bug. You might spend hours debugging your Video.js configuration when the real problem is a syntax error in the caption file.
How to avoid this:
- Always validate the VTT file first using the WebVTT Validator
- Only after validation passes should you debug player configuration
- Check the browser console for VTT parsing errors
Forgetting deployment paths
A path that works locally may break after deployment. This is especially common when using relative paths.
Example:
<!-- Works locally -->
<track src="captions.vtt">
<!-- Breaks after deployment if file structure changes -->
<track src="/assets/captions.vtt">
Solution:
- Use absolute URLs for production:
https://cdn.example.com/captions.vtt - Or use root-relative paths:
/captions/video-1.vtt - Test the VTT URL directly in production before debugging the player
Not testing with the CC button
Some developers assume captions will show automatically. But even with default set, users might have disabled captions in a previous session.
Always test:
- Load the page
- Click the CC button
- Verify your caption track appears in the menu
- Select it and confirm captions display
Mixing up kind=“subtitles” and kind=“captions”
While both work in Video.js, they have different semantic meanings:
kind="captions"→ Includes sound effects and speaker identification (for accessibility)kind="subtitles"→ Translation of dialogue only
Best practice: Use kind="captions" for same-language accessibility, kind="subtitles" for translations.
Real-world troubleshooting examples
Example 1: Captions work locally but not in production
Symptom: Captions display perfectly on localhost but disappear after deploying to your CDN.
Diagnosis:
- Open DevTools Network tab
- Find the VTT file request
- See CORS error: “blocked by CORS policy”
Cause: Your CDN doesn’t allow cross-origin requests.
Fix: Add CORS headers to your CDN configuration or move the VTT file to the same domain as your player.
Example 2: Only the first few captions show
Symptom: The first 2-3 captions appear, then nothing.
Diagnosis: Validate the VTT file and find a syntax error at line 15.
Cause: A malformed timestamp like 00:00:15.00 (missing a digit) causes the parser to stop.
Fix: Correct the timestamp to 00:00:15.000 and re-validate.
Example 3: CC button is grayed out
Symptom: The closed captions button appears but is disabled.
Diagnosis: Check the browser console and see “Failed to load resource: 404”
Cause: The VTT file path is wrong or the file wasn’t uploaded.
Fix: Verify the file exists at the specified URL by opening it directly in the browser.
Frequently asked questions
Can I use SRT files with Video.js?
No, Video.js requires WebVTT format. You must convert SRT to VTT first. Use the Video.js Subtitle Converter for quick conversion.
Why do my captions have weird characters?
This is usually an encoding issue. VTT files must be UTF-8 encoded. If you see garbled text, use the Subtitle Encoding Fixer to convert your file to UTF-8.
Do I need to enable captions in Video.js settings?
Video.js enables caption support by default. You don’t need special configuration unless you want to customize the caption styling or behavior.
Can I style Video.js captions with CSS?
Yes, but with limitations. You can style the caption container, but individual cue styling requires WebVTT cue settings or the Video.js TextTrackSettings API.
What’s the difference between captions and subtitles in Video.js?
- Captions (
kind="captions") include sound effects and speaker IDs for accessibility - Subtitles (
kind="subtitles") are translations of dialogue
Both work the same way technically, but captions are better for accessibility compliance.
Related guides
- How to convert subtitles for Video.js
- Best subtitle format for Video.js
- Why VTT captions are not loading
Related tools
Use the Video.js Subtitle Converter
Convert SRT or ASS subtitles to WebVTT captions for Video.js players and web video workflows. No signup, no upload, and everything runs locally in the browser.
Open Video.js converter