A 100% pure Java library for the Twitter API with no extra dependency
Twitter list creation, management, and member operations.
Create, update, and manage Twitter lists.
interface ListsResources {
/**
* Create a new list
* @param listName Name of the list
* @param isPublicList Whether list is public (true) or private (false)
* @param description List description
* @return Created list
*/
UserList createUserList(String listName, boolean isPublicList, String description) throws TwitterException;
/**
* Update an existing list
* @param listId List ID to update
* @param newListName New name for the list
* @param isPublicList Whether list should be public
* @param newDescription New description
* @return Updated list
*/
UserList updateUserList(long listId, String newListName, boolean isPublicList, String newDescription) throws TwitterException;
/**
* Delete a list
* @param listId List ID to delete
* @return Deleted list
*/
UserList destroyUserList(long listId) throws TwitterException;
}Retrieve lists and list information.
interface ListsResources {
/**
* Get lists owned by a user
* @param screenName User's screen name
* @return Lists owned by user
*/
ResponseList<UserList> getUserLists(String screenName) throws TwitterException;
/**
* Get lists a user is subscribed to
* @param screenName User's screen name
* @return Lists user is subscribed to
*/
ResponseList<UserList> getUserListSubscriptions(String screenName) throws TwitterException;
/**
* Show details of a specific list
* @param listId List ID
* @return List details
*/
UserList showUserList(long listId) throws TwitterException;
/**
* Get tweets from a list
* @param listId List ID
* @param paging Pagination parameters
* @return Tweets from list members
*/
ResponseList<Status> getUserListStatuses(long listId, Paging paging) throws TwitterException;
}Add, remove, and manage list members.
interface ListsResources {
/**
* Add user to list by user ID
* @param listId List ID
* @param userId User ID to add
* @return Updated list
*/
UserList addUserListMember(long listId, long userId) throws TwitterException;
/**
* Add multiple users to list
* @param listId List ID
* @param userIds Array of user IDs to add (max 100)
* @return Updated list
*/
UserList addUserListMembers(long listId, long... userIds) throws TwitterException;
/**
* Remove user from list by user ID
* @param listId List ID
* @param userId User ID to remove
* @return Updated list
*/
UserList deleteUserListMember(long listId, long userId) throws TwitterException;
/**
* Remove multiple users from list
* @param listId List ID
* @param userIds Array of user IDs to remove
* @return Updated list
*/
UserList deleteUserListMembers(long listId, long... userIds) throws TwitterException;
/**
* Get list members
* @param listId List ID
* @param cursor Pagination cursor (-1 for first page)
* @return Paginated list of members
*/
PagableResponseList<User> getUserListMembers(long listId, long cursor) throws TwitterException;
/**
* Check if user is member of list
* @param listId List ID
* @param userId User ID to check
* @return User if member, throws exception if not
*/
User checkUserListMembership(long listId, long userId) throws TwitterException;
}Subscribe to and unsubscribe from lists.
interface ListsResources {
/**
* Subscribe to a list (follow)
* @param listId List ID to subscribe to
* @return Subscribed list
*/
UserList subscribeUserList(long listId) throws TwitterException;
/**
* Unsubscribe from a list (unfollow)
* @param listId List ID to unsubscribe from
* @return Unsubscribed list
*/
UserList unsubscribeUserList(long listId) throws TwitterException;
/**
* Get list subscribers
* @param listId List ID
* @param cursor Pagination cursor (-1 for first page)
* @return Paginated list of subscribers
*/
PagableResponseList<User> getUserListSubscribers(long listId, long cursor) throws TwitterException;
/**
* Check if user is subscribed to list
* @param listId List ID
* @param userId User ID to check
* @return User if subscribed, throws exception if not
*/
User checkUserListSubscription(long listId, long userId) throws TwitterException;
}Usage Examples:
TwitterV1 v1 = twitter.v1();
// Create a new public list
UserList techList = v1.list().createUserList(
"Tech Leaders",
true,
"Influential people in technology"
);
// Add members to the list
v1.list().addUserListMember(techList.getId(), 783214L); // Add by user ID
v1.list().addUserListMembers(techList.getId(), 783214L, 17874544L, 95731L); // Add multiple
// Get tweets from the list
ResponseList<Status> listTweets = v1.list().getUserListStatuses(techList.getId(), null);
for (Status tweet : listTweets) {
System.out.println(tweet.getUser().getScreenName() + ": " + tweet.getText());
}
// Subscribe to another user's list
v1.list().subscribeUserList(anotherListId);
// Get all lists you own
ResponseList<UserList> myLists = v1.list().getUserLists("myusername");
for (UserList list : myLists) {
System.out.println(list.getName() + " (" + list.getMemberCount() + " members)");
}Complete list information and metadata.
interface UserList extends TwitterResponse {
/**
* List unique identifier
*/
long getId();
/**
* List name
*/
String getName();
/**
* List description
*/
String getDescription();
/**
* List owner user
*/
User getUser();
/**
* Number of members in list
*/
int getMemberCount();
/**
* Number of subscribers to list
*/
int getSubscriberCount();
/**
* List creation timestamp
*/
LocalDateTime getCreatedAt();
/**
* Whether list is public
*/
boolean isPublic();
/**
* Whether authenticated user is following this list
*/
boolean isFollowing();
/**
* List slug (URL-friendly name)
*/
String getSlug();
/**
* Full list name (owner/listname)
*/
String getFullName();
/**
* List URI
*/
String getURI();
}public class ListAnalytics {
private final TwitterV1 v1;
public ListStats analyzeList(long listId) throws TwitterException {
UserList list = v1.list().showUserList(listId);
PagableResponseList<User> members = v1.list().getUserListMembers(listId, -1);
ResponseList<Status> recentTweets = v1.list().getUserListStatuses(listId,
Paging.ofCount(200));
ListStats stats = new ListStats();
stats.listName = list.getName();
stats.memberCount = list.getMemberCount();
stats.subscriberCount = list.getSubscriberCount();
// Analyze member activity
stats.averageFollowerCount = members.stream()
.mapToInt(User::getFollowersCount)
.average().orElse(0.0);
stats.verifiedMemberCount = (int) members.stream()
.filter(User::isVerified)
.count();
// Analyze recent activity
stats.recentTweetCount = recentTweets.size();
stats.averageRetweetCount = recentTweets.stream()
.mapToInt(Status::getRetweetCount)
.average().orElse(0.0);
return stats;
}
public static class ListStats {
public String listName;
public int memberCount;
public int subscriberCount;
public double averageFollowerCount;
public int verifiedMemberCount;
public int recentTweetCount;
public double averageRetweetCount;
}
}public class BulkListManager {
private final TwitterV1 v1;
public void populateListFromSearch(long listId, String searchQuery, int maxUsers)
throws TwitterException {
Query query = Query.of(searchQuery).count(100);
QueryResult searchResult = v1.search().search(query);
Set<Long> uniqueUsers = new HashSet<>();
// Collect unique users from search results
for (Status tweet : searchResult.getTweets()) {
uniqueUsers.add(tweet.getUser().getId());
if (uniqueUsers.size() >= maxUsers) break;
}
// Add users to list in batches of 100
List<Long> userList = new ArrayList<>(uniqueUsers);
for (int i = 0; i < userList.size(); i += 100) {
int end = Math.min(i + 100, userList.size());
List<Long> batch = userList.subList(i, end);
long[] batchArray = batch.stream().mapToLong(Long::longValue).toArray();
v1.list().addUserListMembers(listId, batchArray);
// Rate limiting
Thread.sleep(1000);
}
}
public void cleanupInactiveMembers(long listId, int inactiveDays) throws TwitterException {
PagableResponseList<User> members = v1.list().getUserListMembers(listId, -1);
List<Long> toRemove = new ArrayList<>();
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(inactiveDays);
for (User member : members) {
try {
ResponseList<Status> recentTweets = v1.timelines()
.getUserTimeline(member.getId(), Paging.ofCount(1));
if (recentTweets.isEmpty() ||
recentTweets.get(0).getCreatedAt().isBefore(cutoffDate)) {
toRemove.add(member.getId());
}
Thread.sleep(100); // Rate limiting
} catch (TwitterException e) {
if (e.getStatusCode() == 401) {
// Protected account or suspended - remove from list
toRemove.add(member.getId());
}
}
}
// Remove inactive members in batches
for (int i = 0; i < toRemove.size(); i += 100) {
int end = Math.min(i + 100, toRemove.size());
List<Long> batch = toRemove.subList(i, end);
long[] batchArray = batch.stream().mapToLong(Long::longValue).toArray();
v1.list().deleteUserListMembers(listId, batchArray);
Thread.sleep(1000);
}
}
}public class ListCurator {
private final TwitterV1 v1;
public void curateListByTopic(long listId, List<String> keywords, int minFollowers)
throws TwitterException {
PagableResponseList<User> currentMembers = v1.list().getUserListMembers(listId, -1);
Set<Long> relevantMembers = new HashSet<>();
// Analyze current members' recent tweets for relevance
for (User member : currentMembers) {
try {
ResponseList<Status> recentTweets = v1.timelines()
.getUserTimeline(member.getId(), Paging.ofCount(20));
long relevantTweetCount = recentTweets.stream()
.filter(tweet -> containsKeywords(tweet.getText(), keywords))
.count();
// Keep members who tweet about the topic and meet follower threshold
if (relevantTweetCount >= 3 && member.getFollowersCount() >= minFollowers) {
relevantMembers.add(member.getId());
}
Thread.sleep(100);
} catch (TwitterException e) {
// Handle rate limits and errors
if (e.exceededRateLimitation()) {
Thread.sleep(e.getRetryAfter() * 1000);
}
}
}
// Remove irrelevant members
List<Long> toRemove = currentMembers.stream()
.map(User::getId)
.filter(id -> !relevantMembers.contains(id))
.collect(Collectors.toList());
for (long userId : toRemove) {
v1.list().deleteUserListMember(listId, userId);
Thread.sleep(100);
}
}
private boolean containsKeywords(String text, List<String> keywords) {
String lowerText = text.toLowerCase();
return keywords.stream()
.anyMatch(keyword -> lowerText.contains(keyword.toLowerCase()));
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-twitter4j--twitter4j-core