NewPipe Extractor defines a comprehensive exception hierarchy to handle various error conditions that can occur during content extraction. All extraction-specific exceptions extend from ExtractionException.
Exception Hierarchy
Exception
└── ExtractionException
├── ParsingException
│ ├── ContentNotAvailableException
│ │ ├── AgeRestrictedContentException
│ │ ├── GeographicRestrictionException
│ │ ├── PaidContentException
│ │ ├── PrivateContentException
│ │ ├── AccountTerminatedException
│ │ ├── YoutubeMusicPremiumContentException
│ │ ├── SoundCloudGoPlusContentException
│ │ └── UnsupportedContentInCountryException
│ ├── ContentNotSupportedException
│ ├── FoundAdException
│ └── SignInConfirmNotBotException
└── ReCaptchaException
UnsupportedOperationException
└── UnsupportedTabException
Base Exceptions
The root exception for all extraction-related errors. This is the base class that all other extraction exceptions extend.
Constructors
Error message describing what went wrong
throw new ExtractionException("Failed to extract video information");
The underlying cause of this exception
throw new ExtractionException(ioException);
throw new ExtractionException("Failed to parse JSON", jsonException);
When thrown: Base exception rarely thrown directly; use specific subclasses instead.
ReCaptchaException
Thrown when the service requires CAPTCHA verification before proceeding. Extends ExtractionException.
Constructor
The CAPTCHA URL that needs to be solved
if (response.responseCode() == 429) {
throw new ReCaptchaException(
"CAPTCHA required",
"https://www.google.com/recaptcha/..."
);
}
Methods
try {
// Extraction code
} catch (ReCaptchaException e) {
String captchaUrl = e.getUrl();
// Redirect user to solve CAPTCHA
}
When thrown: When a service detects automated requests and requires CAPTCHA verification. Common with YouTube when making too many requests.
Parsing Exceptions
ParsingException
Thrown when content cannot be parsed correctly. This is a general parsing error. Extends ExtractionException.
Constructors
Error message describing the parsing failure
throw new ParsingException("Could not extract video ID from URL");
try {
int viewCount = Integer.parseInt(viewCountStr);
} catch (NumberFormatException e) {
throw new ParsingException("Invalid view count format", e);
}
When thrown: When JSON/HTML parsing fails, regex doesn’t match, or data format is unexpected.
ContentNotSupportedException
Thrown when the content type is not supported by the extractor. Extends ParsingException.
Constructors
throw new ContentNotSupportedException("Shorts are not supported");
When thrown: When encountering content types the extractor doesn’t handle (e.g., live streams, premieres, posts).
FoundAdException
Thrown when an advertisement is encountered instead of actual content. Extends ParsingException.
Constructors
if (isAd(item)) {
throw new FoundAdException("Item is an advertisement");
}
When thrown: When parsing feed items or search results and encountering sponsored/ad content.
SignInConfirmNotBotException
Thrown when the service requires logging in to confirm the user is not a bot. Extends ParsingException.
Constructor
if (requiresSignIn) {
throw new SignInConfirmNotBotException(
"Service requires sign-in to verify you're not a bot"
);
}
When thrown: Usually when the service detects bot-like behavior and requires authentication. Often only solvable by changing IP address (e.g., with YouTube).
Content Availability Exceptions
ContentNotAvailableException
Thrown when content exists but cannot be accessed for various reasons. Extends ParsingException.
Constructors
Error message describing why content is unavailable
throw new ContentNotAvailableException("Video has been removed");
When thrown: Generic availability error. Usually use specific subclasses instead.
AgeRestrictedContentException
Thrown when content is age-restricted and requires verification. Extends ContentNotAvailableException.
Constructors
if (isAgeRestricted) {
throw new AgeRestrictedContentException(
"This video is age-restricted"
);
}
When thrown: When content requires age verification to view (18+ content).
GeographicRestrictionException
Thrown when content is blocked in specific geographic regions due to distribution rights. Extends ContentNotAvailableException.
Constructors
throw new GeographicRestrictionException(
"This video is not available in your country"
);
When thrown: When content is intentionally geo-blocked for licensing/distribution reasons.
UnsupportedContentInCountryException
Thrown when content is not supported in a specific country, but not due to intentional geographic restrictions. Extends ContentNotAvailableException.
Constructors
throw new UnsupportedContentInCountryException(
"This content type is not available in this region"
);
When thrown: When content is unavailable in a country for reasons other than distribution rights. Different from GeographicRestrictionException.
PaidContentException
Thrown when content requires payment to access. Extends ContentNotAvailableException.
Constructors
if (requiresPurchase) {
throw new PaidContentException(
"This content requires payment"
);
}
When thrown: When content is behind a paywall or requires purchase.
PrivateContentException
Thrown when content is private and not publicly accessible. Extends ContentNotAvailableException.
Constructors
if (isPrivate) {
throw new PrivateContentException(
"This video is private"
);
}
When thrown: When content is set to private by the uploader.
YoutubeMusicPremiumContentException
Thrown when encountering YouTube Music Premium exclusive content. Extends ContentNotAvailableException.
Constructors
throw new YoutubeMusicPremiumContentException();
Default message: “This video is a YouTube Music Premium video”
throw new YoutubeMusicPremiumContentException(cause);
When thrown: When extracting YouTube content that requires YouTube Music Premium.
SoundCloudGoPlusContentException
Thrown when encountering SoundCloud Go+ exclusive content. Extends ContentNotAvailableException.
Constructors
throw new SoundCloudGoPlusContentException();
Default message: “This track is a SoundCloud Go+ track”
throw new SoundCloudGoPlusContentException(cause);
When thrown: When extracting SoundCloud content that requires SoundCloud Go+ subscription.
AccountTerminatedException
Thrown when the content owner’s account has been terminated. Extends ContentNotAvailableException.
Constructors
Error message describing the termination
throw new AccountTerminatedException(
"This account has been terminated"
);
The reason for termination
throw new AccountTerminatedException(
"Account terminated for community guidelines violation",
AccountTerminatedException.Reason.VIOLATION
);
Methods
The reason for account termination
Reason Enum
Termination reason is unknown
Account terminated for policy violations
Example:
try {
// Extract content
} catch (AccountTerminatedException e) {
AccountTerminatedException.Reason reason = e.getReason();
if (reason == AccountTerminatedException.Reason.VIOLATION) {
System.out.println("Account terminated for violations");
}
}
When thrown: When attempting to extract content from a terminated channel or account.
Other Exceptions
UnsupportedTabException
Thrown when attempting to access an unsupported tab in a service. Extends UnsupportedOperationException (not ExtractionException).
Constructor
Name of the unsupported tab
if (!supportedTabs.contains(tabName)) {
throw new UnsupportedTabException(tabName);
}
Message format: “Unsupported tab ”
When thrown: When a channel or page tab is not supported by the extractor (e.g., “Store” tab on YouTube).
Exception Handling Examples
Basic Exception Handling
import org.schabi.newpipe.extractor.exceptions.*;
public void extractVideo(String url) {
try {
StreamExtractor extractor = service.getStreamExtractor(url);
extractor.fetchPage();
String title = extractor.getName();
} catch (AgeRestrictedContentException e) {
System.err.println("Age-restricted: " + e.getMessage());
} catch (GeographicRestrictionException e) {
System.err.println("Geo-blocked: " + e.getMessage());
} catch (PrivateContentException e) {
System.err.println("Private video: " + e.getMessage());
} catch (ContentNotAvailableException e) {
System.err.println("Content unavailable: " + e.getMessage());
} catch (ParsingException e) {
System.err.println("Parse error: " + e.getMessage());
} catch (ReCaptchaException e) {
System.err.println("CAPTCHA required at: " + e.getUrl());
} catch (ExtractionException e) {
System.err.println("Extraction failed: " + e.getMessage());
}
}
Specific Service Exceptions
public void extractYouTubeVideo(String url) {
try {
StreamExtractor extractor = YouTube.getStreamExtractor(url);
extractor.fetchPage();
} catch (YoutubeMusicPremiumContentException e) {
System.err.println("Requires YouTube Music Premium");
// Offer user option to subscribe
} catch (AccountTerminatedException e) {
if (e.getReason() == AccountTerminatedException.Reason.VIOLATION) {
System.err.println("Channel terminated for violations");
} else {
System.err.println("Channel no longer available");
}
}
}
public void extractSoundCloudTrack(String url) {
try {
StreamExtractor extractor = SoundCloud.getStreamExtractor(url);
extractor.fetchPage();
} catch (SoundCloudGoPlusContentException e) {
System.err.println("Requires SoundCloud Go+ subscription");
}
}
Categorizing Exceptions
public enum ExtractionErrorType {
UNAVAILABLE,
PARSING_ERROR,
CAPTCHA_REQUIRED,
UNSUPPORTED,
NETWORK_ERROR
}
public ExtractionErrorType categorizeError(Exception e) {
if (e instanceof ContentNotAvailableException) {
return ExtractionErrorType.UNAVAILABLE;
} else if (e instanceof ReCaptchaException) {
return ExtractionErrorType.CAPTCHA_REQUIRED;
} else if (e instanceof ContentNotSupportedException) {
return ExtractionErrorType.UNSUPPORTED;
} else if (e instanceof ParsingException) {
return ExtractionErrorType.PARSING_ERROR;
} else if (e instanceof IOException) {
return ExtractionErrorType.NETWORK_ERROR;
}
return ExtractionErrorType.PARSING_ERROR;
}
Recovery Strategies
public void extractWithRetry(String url, int maxRetries) {
int attempt = 0;
while (attempt < maxRetries) {
try {
StreamExtractor extractor = service.getStreamExtractor(url);
extractor.fetchPage();
return; // Success
} catch (ReCaptchaException e) {
System.err.println("CAPTCHA detected, cannot retry");
throw e; // Can't recover automatically
} catch (ContentNotAvailableException e) {
System.err.println("Content unavailable, cannot retry");
throw e; // Can't recover
} catch (ParsingException e) {
attempt++;
if (attempt >= maxRetries) {
throw e;
}
System.err.println("Parse error, retrying... (" + attempt + ")");
} catch (IOException e) {
attempt++;
if (attempt >= maxRetries) {
throw e;
}
System.err.println("Network error, retrying... (" + attempt + ")");
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException(ie);
}
}
}
}
Best Practices
Catch Specific Exceptions First
Always catch more specific exceptions before general ones:
try {
// Extraction code
} catch (AgeRestrictedContentException e) {
// Handle age restriction
} catch (ContentNotAvailableException e) {
// Handle other availability issues
} catch (ParsingException e) {
// Handle parsing errors
} catch (ExtractionException e) {
// Handle any other extraction error
}
Provide Context in Error Messages
try {
String title = extractor.getName();
} catch (ParsingException e) {
throw new ParsingException(
"Failed to extract video title from URL: " + url,
e
);
}
Log Appropriately
try {
// Extract content
} catch (FoundAdException e) {
// Ads are expected, log at debug level
logger.debug("Skipping ad item");
} catch (ContentNotAvailableException e) {
// Availability issues are common, log at info level
logger.info("Content not available: " + e.getMessage());
} catch (ParsingException e) {
// Parsing errors are more serious, log at warning level
logger.warn("Failed to parse content", e);
}
- Downloader - Throws IOException and ReCaptchaException
- Localization - Throws ParsingException for invalid codes