A 100% pure Java library for the Twitter API with no extra dependency
Access to various Twitter timelines including home timeline, user timeline, and mentions.
Get tweets from users that the authenticated user follows.
interface TimelinesResources {
/**
* Get the 20 most recent tweets from home timeline
* @return List of tweets from followed users
*/
ResponseList<Status> getHomeTimeline() throws TwitterException;
/**
* Get home timeline with pagination
* @param paging Pagination parameters (page, count, since_id, max_id)
* @return List of tweets from followed users
*/
ResponseList<Status> getHomeTimeline(Paging paging) throws TwitterException;
}Usage Examples:
TwitterV1 v1 = twitter.v1();
// Get recent home timeline
ResponseList<Status> homeTimeline = v1.timelines().getHomeTimeline();
for (Status tweet : homeTimeline) {
System.out.println(tweet.getUser().getScreenName() + ": " + tweet.getText());
}
// Get home timeline with pagination
Paging paging = Paging.ofCount(50).sinceId(1234567890L);
ResponseList<Status> paginatedTimeline = v1.timelines().getHomeTimeline(paging);Get tweets posted by a specific user.
interface TimelinesResources {
/**
* Get authenticated user's timeline (20 most recent tweets)
* @return List of user's tweets
*/
ResponseList<Status> getUserTimeline() throws TwitterException;
/**
* Get specific user's timeline by screen name
* @param screenName User's screen name (without @)
* @return List of user's tweets
*/
ResponseList<Status> getUserTimeline(String screenName) throws TwitterException;
/**
* Get specific user's timeline by user ID
* @param userId User's numeric ID
* @return List of user's tweets
*/
ResponseList<Status> getUserTimeline(long userId) throws TwitterException;
/**
* Get user timeline with pagination by screen name
* @param screenName User's screen name (without @)
* @param paging Pagination parameters
* @return List of user's tweets
*/
ResponseList<Status> getUserTimeline(String screenName, Paging paging) throws TwitterException;
/**
* Get user timeline with pagination by user ID
* @param userId User's numeric ID
* @param paging Pagination parameters
* @return List of user's tweets
*/
ResponseList<Status> getUserTimeline(long userId, Paging paging) throws TwitterException;
}Usage Examples:
// Get authenticated user's timeline
ResponseList<Status> myTimeline = v1.timelines().getUserTimeline();
// Get specific user's timeline by screen name
ResponseList<Status> userTweets = v1.timelines().getUserTimeline("twitterapi");
// Get user timeline by ID
ResponseList<Status> userTweetsById = v1.timelines().getUserTimeline(783214L);
// Get user timeline with pagination
Paging paging = Paging.ofCount(100).maxId(9876543210L);
ResponseList<Status> paginatedUserTweets = v1.timelines()
.getUserTimeline("twitterapi", paging);Get tweets that mention the authenticated user.
interface TimelinesResources {
/**
* Get 20 most recent mentions of authenticated user
* @return List of tweets mentioning the user
*/
ResponseList<Status> getMentionsTimeline() throws TwitterException;
/**
* Get mentions timeline with pagination
* @param paging Pagination parameters
* @return List of tweets mentioning the user
*/
ResponseList<Status> getMentionsTimeline(Paging paging) throws TwitterException;
}Usage Examples:
// Get recent mentions
ResponseList<Status> mentions = v1.timelines().getMentionsTimeline();
for (Status mention : mentions) {
System.out.println("@" + mention.getUser().getScreenName() + " mentioned you: " +
mention.getText());
}
// Get mentions with pagination
Paging paging = Paging.ofCount(200).sinceId(1234567890L);
ResponseList<Status> paginatedMentions = v1.timelines().getMentionsTimeline(paging);Get retweets of the authenticated user's tweets.
interface TimelinesResources {
/**
* Get 20 most recent retweets of authenticated user's tweets
* @return List of retweets of user's tweets
*/
ResponseList<Status> getRetweetsOfMe() throws TwitterException;
/**
* Get retweets of user's tweets with pagination
* @param paging Pagination parameters
* @return List of retweets of user's tweets
*/
ResponseList<Status> getRetweetsOfMe(Paging paging) throws TwitterException;
}Usage Examples:
// Get recent retweets of your tweets
ResponseList<Status> myRetweets = v1.timelines().getRetweetsOfMe();
for (Status retweet : myRetweets) {
Status originalTweet = retweet.getRetweetedStatus();
System.out.println("Your tweet retweeted: " + originalTweet.getText());
System.out.println("Retweeted by: " + retweet.getUser().getScreenName());
}
// Get retweets with pagination
Paging paging = Paging.ofCount(50).maxId(9876543210L);
ResponseList<Status> paginatedRetweets = v1.timelines().getRetweetsOfMe(paging);Comprehensive pagination control for timeline requests.
class Paging {
/**
* Create pagination by page number (deprecated approach)
* @param page Page number (1-indexed)
* @return Paging object for page-based pagination
*/
static Paging ofPage(int page);
/**
* Create pagination by count only
* @param count Number of tweets to retrieve (max 200)
* @return Paging object with count setting
*/
static Paging ofCount(int count);
/**
* Set page number (deprecated - use cursor-based pagination instead)
* @param page Page number
* @return Paging with page setting
*/
Paging withPage(int page);
/**
* Set number of tweets per page
* @param count Number of tweets (1-200, default 20)
* @return Paging with count setting
*/
Paging count(int count);
/**
* Set since_id for retrieving tweets newer than specified ID
* @param sinceId Tweet ID - only tweets newer than this will be returned
* @return Paging with since_id setting
*/
Paging sinceId(long sinceId);
/**
* Set max_id for retrieving tweets older than specified ID
* @param maxId Tweet ID - only tweets older than this will be returned
* @return Paging with max_id setting
*/
Paging maxId(long maxId);
/**
* Get current page number
*/
int getPage();
/**
* Get current count setting
*/
int getCount();
/**
* Get current since_id setting
*/
long getSinceId();
/**
* Get current max_id setting
*/
long getMaxId();
}Pagination Strategies:
TwitterV1 v1 = twitter.v1();
// Strategy 1: Get latest tweets (since a specific tweet)
long lastSeenId = 1234567890L;
Paging newTweets = Paging.ofCount(50).sinceId(lastSeenId);
ResponseList<Status> latest = v1.timelines().getHomeTimeline(newTweets);
// Strategy 2: Get older tweets (before a specific tweet)
long oldestId = 9876543210L;
Paging olderTweets = Paging.ofCount(100).maxId(oldestId - 1);
ResponseList<Status> older = v1.timelines().getHomeTimeline(olderTweets);
// Strategy 3: Get maximum tweets per request
Paging maxTweets = Paging.ofCount(200); // 200 is the maximum
ResponseList<Status> bulk = v1.timelines().getHomeTimeline(maxTweets);
// Strategy 4: Continuous pagination through timeline
long maxId = Long.MAX_VALUE;
List<Status> allTweets = new ArrayList<>();
while (allTweets.size() < 1000) { // Stop after 1000 tweets
Paging paging = Paging.ofCount(200).maxId(maxId - 1);
ResponseList<Status> batch = v1.timelines().getHomeTimeline(paging);
if (batch.isEmpty()) break; // No more tweets
allTweets.addAll(batch);
maxId = batch.get(batch.size() - 1).getId();
}All timeline endpoints have rate limits that should be monitored.
ResponseList<Status> timeline = v1.timelines().getHomeTimeline();
// Check rate limit status
RateLimitStatus rateLimit = timeline.getRateLimitStatus();
System.out.println("Remaining requests: " + rateLimit.getRemaining());
System.out.println("Rate limit resets at: " +
Instant.ofEpochSecond(rateLimit.getResetTimeInSeconds()));
if (rateLimit.getRemaining() < 5) {
// Approaching rate limit - consider backing off
int sleepTime = rateLimit.getSecondsUntilReset();
System.out.println("Rate limit low, sleeping for " + sleepTime + " seconds");
Thread.sleep(sleepTime * 1000);
}public class TimelineMonitor {
private final TwitterV1 v1;
private long lastSeenId = 1L;
public TimelineMonitor(TwitterV1 v1) {
this.v1 = v1;
}
public List<Status> getNewTweets() throws TwitterException {
Paging paging = Paging.ofCount(200).sinceId(lastSeenId);
ResponseList<Status> newTweets = v1.timelines().getHomeTimeline(paging);
if (!newTweets.isEmpty()) {
lastSeenId = newTweets.get(0).getId();
}
return newTweets;
}
public void monitorTimeline() {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
List<Status> newTweets = getNewTweets();
for (Status tweet : newTweets) {
processTweet(tweet);
}
} catch (TwitterException e) {
System.err.println("Error fetching timeline: " + e.getMessage());
}
}, 0, 60, TimeUnit.SECONDS); // Check every minute
}
private void processTweet(Status tweet) {
// Process new tweet
System.out.println("New tweet: " + tweet.getText());
}
}public class TimelineAnalyzer {
private final TwitterV1 v1;
public List<Status> getAllUserTweets(String screenName, int maxTweets)
throws TwitterException {
List<Status> allTweets = new ArrayList<>();
long maxId = Long.MAX_VALUE;
while (allTweets.size() < maxTweets) {
int remaining = Math.min(200, maxTweets - allTweets.size());
Paging paging = Paging.ofCount(remaining).maxId(maxId - 1);
ResponseList<Status> batch = v1.timelines()
.getUserTimeline(screenName, paging);
if (batch.isEmpty()) break;
allTweets.addAll(batch);
maxId = batch.get(batch.size() - 1).getId();
// Respect rate limits
RateLimitStatus rateLimit = batch.getRateLimitStatus();
if (rateLimit.getRemaining() <= 1) {
try {
Thread.sleep(rateLimit.getSecondsUntilReset() * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
return allTweets;
}
}public class TimelineFilter {
public List<Status> filterTweets(ResponseList<Status> timeline,
Predicate<Status> filter) {
return timeline.stream()
.filter(filter)
.collect(Collectors.toList());
}
// Common filters
public static Predicate<Status> originalTweetsOnly() {
return tweet -> tweet.getRetweetedStatus() == null;
}
public static Predicate<Status> retweetsOnly() {
return tweet -> tweet.getRetweetedStatus() != null;
}
public static Predicate<Status> withMedia() {
return tweet -> tweet.getMediaEntities().length > 0;
}
public static Predicate<Status> withHashtag(String hashtag) {
return tweet -> Arrays.stream(tweet.getHashtagEntities())
.anyMatch(entity -> entity.getText().equalsIgnoreCase(hashtag));
}
public static Predicate<Status> fromUser(String screenName) {
return tweet -> tweet.getUser().getScreenName()
.equalsIgnoreCase(screenName);
}
public static Predicate<Status> newerThan(LocalDateTime time) {
return tweet -> tweet.getCreatedAt().isAfter(time);
}
}
// Usage example
ResponseList<Status> timeline = v1.timelines().getHomeTimeline();
List<Status> originalTweetsWithMedia = new TimelineFilter()
.filterTweets(timeline,
TimelineFilter.originalTweetsOnly()
.and(TimelineFilter.withMedia())
.and(TimelineFilter.newerThan(LocalDateTime.now().minusHours(24)))
);All timeline methods return ResponseList<Status> with rate limiting information.
interface ResponseList<T> extends List<T>, TwitterResponse {
/**
* Get rate limit status for this response
*/
RateLimitStatus getRateLimitStatus();
/**
* Get access level for this response
*/
int getAccessLevel();
}Each timeline entry is a Status object containing tweet data.
interface Status {
/**
* Tweet creation timestamp
*/
LocalDateTime getCreatedAt();
/**
* Unique tweet identifier
*/
long getId();
/**
* Tweet text content
*/
String getText();
/**
* Tweet author information
*/
User getUser();
/**
* Whether this is a retweet
*/
boolean isRetweet();
/**
* Original tweet if this is a retweet
*/
Status getRetweetedStatus();
/**
* Reply information
*/
long getInReplyToStatusId();
String getInReplyToScreenName();
/**
* Engagement metrics
*/
int getRetweetCount();
int getFavoriteCount();
/**
* User interaction status
*/
boolean isRetweeted();
boolean isFavorited();
/**
* Tweet entities (URLs, mentions, hashtags, media)
*/
URLEntity[] getURLEntities();
UserMentionEntity[] getUserMentionEntities();
HashtagEntity[] getHashtagEntities();
MediaEntity[] getMediaEntities();
/**
* Geographic information
*/
GeoLocation getGeoLocation();
Place getPlace();
}Timeline operations can fail due to various reasons including rate limiting, authentication issues, or user privacy settings.
try {
ResponseList<Status> timeline = v1.timelines().getUserTimeline("privateuser");
} catch (TwitterException e) {
switch (e.getStatusCode()) {
case 401:
System.out.println("User's tweets are protected");
break;
case 404:
System.out.println("User not found");
break;
case 429:
System.out.println("Rate limit exceeded");
int retryAfter = e.getRetryAfter();
System.out.println("Retry after " + retryAfter + " seconds");
break;
default:
System.out.println("API error: " + e.getMessage());
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-twitter4j--twitter4j-core