diff --git a/espncricinfo/exceptions.py b/espncricinfo/exceptions.py
index ebf89f8..315cab7 100644
--- a/espncricinfo/exceptions.py
+++ b/espncricinfo/exceptions.py
@@ -24,4 +24,16 @@ class NoSeriesError(TypeError):
     """
     Exception raised if a series_id is not valid or does not exist.
     """
-    pass
\ No newline at end of file
+    pass
+
+class NoSeasonError(TypeError):
+    """
+    Exception raised if a series_id is not valid or does not exist.
+    """
+    pass
+
+class NoTeamError(TypeError):
+    """
+    Exception raised if a series_id is not valid or does not exist.
+    """
+    pass
diff --git a/espncricinfo/livematches.py b/espncricinfo/livematches.py
new file mode 100644
index 0000000..13df5aa
--- /dev/null
+++ b/espncricinfo/livematches.py
@@ -0,0 +1,93 @@
+import requests, re
+from bs4 import BeautifulSoup
+
+class Team(object):
+    def __init__(self, teamname, score):
+        self.name = teamname
+        self.score = score
+
+class LiveMatch(object):
+    def __init__(self, match_time, match_id, match_number, venue, date, year, series, teams, match_status):
+        self.match_time = match_time
+        self.match_id = match_id
+        self.match_number = match_number
+        self.venue = venue
+        self.date = date
+        self.year = year
+        self.series = series
+        self.teams = teams
+        self.match_status = match_status
+        self.match_name = f"{teams[0].name} vs {teams[1].name}"
+
+    def __repr__(self):
+        teams_info = " | ".join([f"{team[0]}: {team[1]}" for team in self.teams])
+        return (f"Match Time: {self.match_time}\n"
+                f"Match Number: {self.match_number}\n"
+                f"Venue: {self.venue}\n"
+                f"Date: {self.date}, {self.year}\n"
+                f"Series: {self.series}\n"
+                f"Teams: {teams_info}\n"
+                f"Status: {self.match_status}\n")
+
+class LiveMatches:
+    
+    def __init__(self):
+        self.match_url = "https://www.espncricinfo.com/live-cricket-score"
+        self.headers = {'user-agent': 'Mozilla/5.0'}
+        self._live_matches = []
+        self.html = None
+    
+    @property
+    def live_matches(self):
+        if not self._live_matches:
+            self._get_live_matches()
+        return self._live_matches
+    
+    def _fetch_html(self):
+        response = requests.get(self.match_url, headers=self.headers)
+        if response.status_code != 200:
+            print("Failed to retrieve page")
+            return None
+        return BeautifulSoup(response.text, "html.parser")
+
+    def _get_live_matches(self):
+        self.html = self._fetch_html()
+        if not self.html:
+            return []
+        
+        parent_div = self.html.select_one("html > body > div > section > section > div:nth-of-type(3) > div > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(3) > div > div:nth-of-type(1) > div > div:nth-of-type(2) > div")
+        if parent_div:
+            for match_ in parent_div.find_all(recursive=False):
+                span_text = match_.select_one("span.ds-text-tight-xs.ds-font-bold.ds-uppercase.ds-leading-5")
+                div_text = match_.select_one("div.ds-text-tight-xs.ds-truncate.ds-text-typo-mid3")
+                match_time = span_text.text.strip() if span_text else "N/A"
+                match_date = div_text.text.strip() if div_text else "N/A"
+                
+                teams = []
+                teams_div = match_.select_one("div.ds-flex.ds-flex-col.ds-mt-2.ds-mb-2")
+                for team in teams_div.find_all("div", class_="ci-team-score"):
+                    team_div = team.find("div", class_="ds-flex ds-items-center ds-min-w-0 ds-mr-1")
+                    team_name = team_div.get("title") if team_div else "Unknown"
+                    score_div = team.find("div", class_="ds-text-compact-s")
+                    if score_div:
+                        overs_target = score_div.select_one('span[class*="ds-mr-0.5"]')
+                        overs_target_text = overs_target.text.strip() if overs_target else ""
+                        scores = [s.text.strip() for s in score_div.select("strong")]
+                        formatted_score = f"{overs_target_text} {' & '.join(scores)}" if overs_target_text else " & ".join(scores)
+                    else:
+                        formatted_score = None
+                    teams.append(Team(team_name, formatted_score))
+                
+                if match_date != "N/A":
+                    match_number, venue, date, year, series = match_date.split(", ")
+                else:
+                    match_number = venue = date = year = series = "N/A"
+                
+                match_status_p = match_.find("p", class_="ds-text-tight-s ds-font-medium ds-truncate ds-text-typo")
+                match_status = match_status_p.text.strip() if match_status_p else "N/A"
+                a_div = match_.select_one("a.ds-no-tap-higlight")
+                match_url = a_div.get("href") or ""
+                match_id = re.search(r'-(\d+)/[^/]+$', match_url).group(1)
+                
+                self._live_matches.append(LiveMatch(match_time, match_id, match_number, venue, date, year, series, teams, match_status))
+        return self._live_matches
diff --git a/espncricinfo/match.py b/espncricinfo/match.py
index e96bc8a..60a7988 100644
--- a/espncricinfo/match.py
+++ b/espncricinfo/match.py
@@ -1,6 +1,7 @@
 import json
 import requests
 from bs4 import BeautifulSoup
+from espncricinfo.misc import *
 from espncricinfo.exceptions import MatchNotFoundError, NoScorecardError
 
 class Match(object):
@@ -47,12 +48,12 @@ def __init__(self, match_id):
             self.followon = self._followon()
             self.scheduled_overs = self._scheduled_overs()
             self.innings_list = self._innings_list()
-            self.innings = self._innings()
-            self.latest_batting = self._latest_batting()
-            self.latest_bowling = self._latest_bowling()
+            self.innings = [ Inning(inn) for inn in self._innings() ]
+            self.latest_batting = [ Batsman(bdata) for bdata in (self._latest_batting() or []) if bdata ]
+            self.latest_bowling = [ Bowler(bldata) for bldata in (self._latest_bowling() or []) if bldata ]
             self.latest_innings = self._latest_innings()
             self.latest_innings_fow = self._latest_innings_fow()
-            self.team_1 = self._team_1()
+            self.team_1 = Team(self._team_1())
             self.team_1_id = self._team_1_id()
             self.team_1_abbreviation = self._team_1_abbreviation()
             self.team_1_players = self._team_1_players()
@@ -60,7 +61,7 @@ def __init__(self, match_id):
             self.team_1_run_rate = self._team_1_run_rate()
             self.team_1_overs_batted = self._team_1_overs_batted()
             self.team_1_batting_result = self._team_1_batting_result()
-            self.team_2 = self._team_2()
+            self.team_2 = Team(self._team_2())
             self.team_2_id = self._team_2_id()
             self.team_2_abbreviation = self._team_2_abbreviation()
             self.team_2_players = self._team_2_players()
@@ -68,6 +69,8 @@ def __init__(self, match_id):
             self.team_2_run_rate = self._team_2_run_rate()
             self.team_2_overs_batted = self._team_2_overs_batted()
             self.team_2_batting_result = self._team_2_batting_result()
+            self.note = self._note()
+            self.live = self._live()
             if not self.status == 'dormant':
                 self.home_team = self._home_team()
                 self.batting_first = self._batting_first()
@@ -133,6 +136,13 @@ def __str__(self):
     def __unicode__(self):
         return self.json['description']
 
+    def _note(self):
+        return self.json['live']['status']
+
+    def _live(self):
+        live = Live(self.json['live'])
+        return live
+
     def _status(self):
         return self.match_json()['match_status']
 
@@ -339,54 +349,78 @@ def _team_2_batting_result(self):
             return None
 
     def _home_team(self):
-        if self._team_1_id() == self.match_json()['home_team_id']:
+        home_team_id = self.match_json().get('home_team_id', None)
+        if not home_team_id:
+            return None
+        if self._team_1_id() == home_team_id:
             return self._team_1_abbreviation()
         else:
             return self._team_2_abbreviation()
 
     def _batting_first(self):
-        if self._team_1_id() == self.match_json()['batting_first_team_id']:
+        batting_first_team_id = self.match_json().get('batting_first_team_id', None)
+        if not batting_first_team_id:
+            return None
+        if self._team_1_id() == batting_first_team_id:
             return self._team_1_abbreviation()
         else:
             return self._team_2_abbreviation()
 
     def _match_winner(self):
-        if self._team_1_id() == self.match_json()['winner_team_id']:
+        winner_team_id = self.match_json().get('winner_team_id', None)
+        if not winner_team_id:
+            return None
+        if self._team_1_id() == winner_team_id:
             return self._team_1_abbreviation()
         else:
             return self._team_2_abbreviation()
 
     def _toss_winner(self):
-        if self._team_1_id() == self.match_json()['toss_winner_team_id']:
+        toss_winner_team_id = self.match_json().get('toss_winner_team_id', None)
+        if not toss_winner_team_id:
+            return None
+        if self._team_1_id() == toss_winner_team_id:
             return self._team_1_id()
         else:
             return self._team_2_id()
 
     def _toss_decision(self):
-        if self.match_json()['toss_decision'] == '' and len(self.innings) > 0:
-            if self.innings[0]['batting_team_id'] == self.toss_winner:
+        toss_decision = self.match_json().get('toss_decision', None)
+        if not toss_decision:
+            return None
+        if toss_decision == '' and len(self.innings) > 0:
+            if self.innings[0].batting_team_id == self.toss_winner:
                 decision = '1'
             else:
                 decision = '2'
         else:
-            decision = self.match_json()['toss_decision']
+            decision = toss_decision
         return decision
 
     def _toss_decision_name(self):
-        if self.match_json()['toss_decision_name'] == '' and len(self.innings) > 0:
-            if self.innings[0]['batting_team_id'] == self.toss_winner:
+        toss_decision_name = self.match_json().get('toss_decision_name', None)
+        if not toss_decision_name:
+            return None
+        if toss_decision_name == '' and len(self.innings) > 0:
+            if self.innings[0].batting_team_id == self.toss_winner:
                 decision_name = 'bat'
             else:
                 decision_name = 'bowl'
         else:
-            decision_name = self.match_json()['toss_decision_name']
+            decision_name = toss_decision_name
         return decision_name
 
     def _toss_choice_team_id(self):
-        return self.match_json()['toss_choice_team_id']
+        toss_choice_team_id = self.match_json().get('toss_choice_team_id', None)
+        if not toss_choice_team_id:
+            return None
+        return toss_choice_team_id
 
     def _toss_winner_team_id(self):
-        return self.match_json()['toss_winner_team_id']
+        toss_winner_team_id = self.match_json().get('toss_winner_team_id', None)
+        if not toss_winner_team_id:
+            return None
+        return toss_winner_team_id
 
     # comms_json methods
 
diff --git a/espncricinfo/misc.py b/espncricinfo/misc.py
new file mode 100644
index 0000000..1d6c692
--- /dev/null
+++ b/espncricinfo/misc.py
@@ -0,0 +1,206 @@
+
+class BatterPlaying:
+    def __init__(self, batting_data):
+        self.balls_faced = int(batting_data.get("balls_faced") or 0)
+        self.batting_position = int(batting_data.get("batting_position") or 0)
+        self.fours = int(batting_data.get("fours") or 0)
+        self.innings_number = int(batting_data.get("innings_number") or 0)
+        self.live_current = int(batting_data.get("live_current") or 0)
+        self.is_batting = batting_data.get("live_current_name") == "striker"
+        self.minutes = int(batting_data.get("minutes") or 0)
+        self.player_id = int(batting_data.get("player_id") or 0)
+        self.runs = int(batting_data.get("runs") or 0)
+        self.sixes = int(batting_data.get("sixes") or 0)
+        self.team_id = int(batting_data.get("team_id") or 0)
+        self.strike_rate = batting_data.get("strike_rate") or "0.0"
+
+    def __repr__(self):
+        return f"BatterPlaying(Player ID: {self.player_id}, Runs: {self.runs}, Balls Faced: {self.balls_faced})"
+
+class BowlerPlaying:
+    def __init__(self, bowling_data):
+        self.player_id = int(bowling_data.get("player_id") or 0)
+        self.team_id = int(bowling_data.get("team_id") or 0)
+        self.innings_number = int(bowling_data.get("innings_number") or 0)
+        self.overs = float(bowling_data.get("overs") or 0.0)
+        self.maidens = int(bowling_data.get("maidens") or 0)
+        self.conceded = int(bowling_data.get("conceded") or 0)
+        self.wickets = int(bowling_data.get("wickets") or 0)
+        self.economy_rate = float(bowling_data.get("economy_rate") or 0.0)
+        self.noballs = int(bowling_data.get("noballs") or 0)
+        self.wides = int(bowling_data.get("wides") or 0)
+        self.live_current = int(bowling_data.get("live_current") or 0)
+        self.is_bowling = bowling_data.get("live_current_name", "") == "current bowler"
+
+    def __repr__(self):
+        return f"BowlerPlaying(Player ID: {self.player_id}, Overs: {self.overs}, Wickets: {self.wickets}, Economy: {self.economy_rate})"
+
+class Batsman:
+    def __init__(self, data):
+        self.balls_faced = int(data.get("balls_faced") or 0)
+        self.hand = data.get("hand", "")
+        self.image_path = data.get("image_path", "")
+        self.name = data.get("known_as", "")
+        self.notout = int(data.get("notout") or 0)
+        self.player_id = int(data.get("player_id") or 0)
+        self.popular_name = data.get("popular_name", "")
+        self.position = int(data.get("position") or 0)
+        self.position_group = data.get("position_group", "")
+        self.runs = int(data.get("runs") or 0)
+
+    def __str__(self):
+        return (f"Batsman {self.known_as} (ID: {self.player_id}): "
+                f"Runs: {self.runs}, Balls Faced: {self.balls_faced}, "
+                f"Position: {self.position} ({self.position_group}), "
+                f"Not Out: {'Yes' if self.notout else 'No'}")
+
+class Bowler:
+    def __init__(self, data):
+        self.conceded = int(data.get("conceded") or 0)
+        self.hand = data.get("hand", "")
+        self.image_path = data.get("image_path", "")
+        self.name = data.get("known_as", "")
+        self.maidens = int(data.get("maidens") or 0)
+        self.overs = float(data.get("overs") or 0.0)
+        self.pacespin = data.get("pacespin", "")
+        self.player_id = int(data.get("player_id") or 0)
+        self.popular_name = data.get("popular_name", "")
+        self.position = int(data.get("position") or 0)
+        self.wickets = int(data.get("wickets") or 0)
+        self.is_bowling = data.get("live_current_name", "") == "current bowler"
+        self.is_previous = data.get("live_current_name", "") == "previous bowler"
+
+    def __str__(self):
+        return (f"Bowler {self.known_as} (ID: {self.player_id}): "
+                f"Wickets: {self.wickets}, Overs: {self.overs}, Runs Conceded: {self.conceded}, "
+                f"Maidens: {self.maidens}, Bowling Style: {self.pacespin}, "
+                f"Hand: {self.hand}, Position: {self.position}, "
+                f"Current Status: {self.live_current_name}")
+
+class Inning:
+    def __init__(self, data):
+        self.ball_limit = int(data.get("ball_limit") or 0)
+        self.balls = int(data.get("balls") or 0)
+        self.batted = int(data.get("batted") or 0)
+        self.batting_team_id = int(data.get("batting_team_id") or 0)
+        self.bowling_team_id = int(data.get("bowling_team_id") or 0)
+        self.bpo = int(data.get("bpo") or 6)
+        self.byes = int(data.get("byes") or 0)
+        self.event = int(data.get("event") or 0)
+        self.event_name = data.get("event_name", "")
+        self.extras = int(data.get("extras") or 0)
+        self.number = int(data.get("innings_number") or 0)
+        self.numth = data.get("innings_numth", "")
+        self.lead = int(data.get("lead") or 0)
+        self.legbyes = int(data.get("legbyes") or 0)
+        self.live_current = int(data.get("live_current") or 0)
+        self.live_current_name = data.get("live_current_name", "")
+        self.minutes = data.get("minutes")
+        self.noballs = int(data.get("noballs") or 0)
+        self.old_penalty_or_bonus = int(data.get("old_penalty_or_bonus") or 0)
+        self.over_limit = float(data.get("over_limit") or 0.0)
+        self.over_limit_run_rate = float(data.get("over_limit_run_rate") or 0.0)
+        self.over_split_limit = float(data.get("over_split_limit") or 0.0)
+        self.overs = float(data.get("overs") or 0.0)
+        self.overs_docked = int(data.get("overs_docked") or 0)
+        self.penalties = int(data.get("penalties") or 0)
+        self.penalties_field_end = int(data.get("penalties_field_end") or 0)
+        self.penalties_field_start = int(data.get("penalties_field_start") or 0)
+        self.run_rate = float(data.get("run_rate") or 0.0)
+        self.runs = int(data.get("runs") or 0)
+        self.target = int(data.get("target") or 0)
+        self.wickets = int(data.get("wickets") or 0)
+        self.wides = int(data.get("wides") or 0)
+
+    def __str__(self):
+        return (f"Innings {self.innings_number} ({self.innings_numth}): "
+                f"{self.batting_team_id} vs {self.bowling_team_id}, "
+                f"Runs: {self.runs}, Wickets: {self.wickets}, Overs: {self.overs}, "
+                f"Run Rate: {self.run_rate}, Event: {self.event_name}")
+
+class Player:
+    def __init__(self, player_data):
+        self.age_days = int(player_data.get("age_days") or 0)
+        self.age_years = int(player_data.get("age_years") or 0)
+        self.alpha_name = player_data.get("alpha_name")
+        self.batting_hand = player_data.get("batting_hand")
+        self.batting_style = player_data.get("batting_style")
+        self.batting_style_long = player_data.get("batting_style_long")
+        self.bowling_hand = player_data.get("bowling_hand")
+        self.bowling_pacespin = player_data.get("bowling_pacespin")
+        self.bowling_style = player_data.get("bowling_style")
+        self.bowling_style_long = player_data.get("bowling_style_long")
+        self.captain = int(player_data.get("captain") or 0)
+        self.card_long = player_data.get("card_long")
+        self.card_qualifier = player_data.get("card_qualifier")
+        self.card_short = player_data.get("card_short")
+        self.dob = player_data.get("dob")
+        self.image_id = int(player_data.get("image_id") or 0)
+        self.keeper = int(player_data.get("keeper") or 0)
+        self.name = player_data.get("known_as")
+        self.match_player_id = int(player_data.get("match_player_id") or 0)
+        self.mobile_name = player_data.get("mobile_name")
+        self.object_id = int(player_data.get("object_id") or 0)
+        self.id = int(player_data.get("player_id") or 0)
+        self.name_id = player_data.get("player_name_id", "0")
+        self.primary_role = player_data.get("player_primary_role")
+        self.style_id = int(player_data.get("player_style_id") or 0)
+        self.p_type = int(player_data.get("player_type") or 0)
+        self.type_name = player_data.get("player_type_name")
+        self.popular_name = player_data.get("popular_name")
+        self.portrait_alt_id = player_data.get("portrait_alt_id")
+        self.portrait_object_id = int(player_data.get("portrait_object_id") or 0)
+        self.status_id = int(player_data.get("status_id") or 0)
+    
+    def __repr__(self):
+        return f"Player({self.known_as}, {self.batting_hand}, {self.bowling_style_long})"
+
+class Team:
+    def __init__(self, team_data):
+        self.batsmen_in_side = int(team_data.get("batsmen_in_side") or 0)
+        self.content_id = int(team_data.get("content_id") or 0)
+        self.country_id = int(team_data.get("country_id") or 0)
+        self.fielders_in_side = int(team_data.get("fielders_in_side") or 0)
+        self.image_id = int(team_data.get("image_id") or 0)
+        self.logo_alt_id = team_data.get("logo_alt_id")
+        self.logo_espncdn = team_data.get("logo_espncdn")
+        self.logo_height = int(team_data.get("logo_height") or 0)
+        self.logo_image_height = int(team_data.get("logo_image_height") or 0)
+        self.logo_image_path = team_data.get("logo_image_path")
+        self.logo_image_width = int(team_data.get("logo_image_width") or 0)
+        self.logo_object_id = int(team_data.get("logo_object_id") or 0)
+        self.logo_path = team_data.get("logo_path")
+        self.logo_width = int(team_data.get("logo_width") or 0)
+        self.object_id = int(team_data.get("object_id") or 0)
+        self.players = [Player(p) for p in team_data.get("player", [])]
+        self.players_in_side = int(team_data.get("players_in_side") or 0)
+        self.site_id = int(team_data.get("site_id") or 0)
+        self.abbreviation = team_data.get("team_abbreviation")
+        self.filename = team_data.get("team_filename")
+        self.general_name = team_data.get("team_general_name")
+        self.id = int(team_data.get("team_id") or 0)
+        self.name = team_data.get("team_name")
+        self.short_name = team_data.get("team_short_name")
+        self.url_component = team_data.get("url_component")
+    
+    def __repr__(self):
+        return f"Team({self.team_name}, Players: {len(self.players)})"
+
+class Live:
+    def __init__(self, json_data):
+        self.batting = [ BatterPlaying(data) for data in json_data['batting'] ]
+        self.bowling = [ BowlerPlaying(data) for data in json_data['bowling'] ]
+        self.status = json_data['status']
+        self.ball_limit = int(json_data.get('innings', {}).get('ball_limit') or 0)
+        self.balls = int(json_data.get('innings', {}).get('balls') or 0)
+        self.current_inning = int(json_data.get('innings', {}).get('innings_number') or 0)
+        self.batting_team_id = int(json_data.get('innings', {}).get('batting_team_id') or 0)
+        self.bowling_team_id = int(json_data.get('innings', {}).get('bowling_team_id') or 0)
+        self.overs = float(json_data.get('innings', {}).get('overs') or 0.0)
+        self.remaining_balls = int(json_data.get('innings', {}).get('remaining_balls') or 0)
+        self.rrr = float(json_data.get('innings', {}).get('required_run_rate') or 0.0)
+        self.crr = float(json_data.get('innings', {}).get('run_rate') or 0.0)
+        self.runs = int(json_data.get('innings', {}).get('runs') or 0)
+        self.target = int(json_data.get('innings', {}).get('target') or 0)
+        self.team_id = int(json_data.get('innings', {}).get('team_id') or 0)
+        self.wickets = int(json_data.get('innings', {}).get('wickets') or 0)
diff --git a/espncricinfo/seasons.py b/espncricinfo/seasons.py
new file mode 100644
index 0000000..0f466b8
--- /dev/null
+++ b/espncricinfo/seasons.py
@@ -0,0 +1,63 @@
+import requests
+from datetime import datetime
+from espncricinfo.exceptions import NoSeasonError
+
+class Season:
+    def __init__(self, season_id, series_id=8039):
+        self.id = season_id
+        self.series_id = series_id
+        self.json_url = f"http://core.espnuk.org/v2/sports/cricket/leagues/{series_id}/seasons/{season_id}"        
+        self.headers = {'user-agent': 'Mozilla/5.0'}
+        self.json = self.get_json(self.json_url)
+        
+        if self.json:
+            self.year = self.json.get('year')
+            self.start_date = self.parse_date(self.json.get('startDate'))
+            self.end_date = self.parse_date(self.json.get('endDate'))
+            self.name = self.json.get('name')
+            self.short_name = self.json.get('shortName')
+            self.slug = self.json.get('slug')
+            self._teams_url = self.json.get('teams', {}).get('$ref')
+            self._series = None
+            self._teams = []
+            self.rankings_url = self.json.get('rankings', {}).get('$ref')
+    
+    @property
+    def series(self):
+        if self._series is None:
+            from espncricinfo.series import Series
+            links = self.json.get('links', [])
+            if links and len(links)>5:
+                series_url = links[5]["href"]
+                series_id = series_url.split("/series/")[-1].split(".html")[0]
+                self._series = Series(series_id)
+        return self._series
+    
+    @property
+    def teams(self):
+        if self._teams is None:
+            from espncricinfo.teams import Team
+            teams_json = self.get_json(self._teams_url)
+            teams_ = teams_json.get('items', [])
+            for t in teams_:
+                team_id = t.split("/teams/")[-1]
+                team_ = Team(team_id)
+                self._teams.append(team_)
+        return self._teams
+    
+    def get_json(self, url):
+        response = requests.get(url, headers=self.headers)
+        if response.status_code == 404:
+            raise NoSeasonError("Season not found.")
+        return response.json()
+    
+    def parse_date(self, date_str):
+        if date_str:
+            return datetime.strptime(date_str, "%Y-%m-%dT%H:%MZ")
+        return None
+    
+    def __str__(self):
+        return self.name if self.name else "Unknown Season"
+    
+    def __repr__(self):
+        return f"Season(id={self.id}, year={self.year}, name={self.name}, start_date={self.start_date}, end_date={self.end_date})"
diff --git a/espncricinfo/series.py b/espncricinfo/series.py
index 7999d5e..677b408 100644
--- a/espncricinfo/series.py
+++ b/espncricinfo/series.py
@@ -1,17 +1,17 @@
 import requests
-from bs4 import BeautifulSoup
 from espncricinfo.exceptions import MatchNotFoundError, NoSeriesError
+from espncricinfo.match import Match
 
 class Series(object):
-
     def __init__(self, series_id):
         self.series_id = series_id
         self.json_url = "http://core.espnuk.org/v2/sports/cricket/leagues/{0}/".format(str(series_id))
-        self.events_url = "http://core.espnuk.org/v2/sports/cricket/leagues/{0}/events".format(str(series_id))
         self.seasons_url = "http://core.espnuk.org/v2/sports/cricket/leagues/{0}/seasons".format(str(series_id))
         self.headers = {'user-agent': 'Mozilla/5.0'}
         self.json = self.get_json(self.json_url)
-        self.seasons = self._get_seasons()
+        self._seasons = []
+        self.events_url = f"{0}/events".format(self.seasons[0])
+        self._current_season = None
         self.years = self._get_years_from_seasons()
         if self.json:
             self.name = self.json['name']
@@ -24,6 +24,29 @@ def __init__(self, series_id):
 
         if self.events_json:
             self.events = self._build_events()
+            self.current_events = self._get_current_events()
+            self.matches = self._build_matches()
+            self.current_matches = self._get_current_matches()
+    
+    @property
+    def seasons(self):
+        if not self._seasons:
+            from espncricinfo.seasons import Season
+            season_json = self.get_json(self.seasons_url)
+            if season_json:
+                season_urls = [x['$ref'] for x in season_json['items']]
+                for url in season_urls:
+                    season = Season(url.split("/seasons/")[-1])
+                    self._seasons.append(season)
+                if len(self._seasons) > 0:
+                    self._current_season = self._seasons[0]
+        return self._seasons
+    
+    @property
+    def current_season(self):
+        if not self._current_season:
+            self.seasons()
+        return self._current_season
 
     def get_json(self, url):
         r = requests.get(url,headers=self.headers)
@@ -38,13 +61,6 @@ def __str__(self):
     def __unicode__(self):
         return self.name
 
-    def _get_seasons(self):
-        season_json = self.get_json(self.seasons_url)
-        if season_json:
-            return [x['$ref'] for x in season_json['items']]
-        else:
-            return None
-
     def _get_years_from_seasons(self):
         return [x.split('/')[9] for x in self.seasons]
 
@@ -55,8 +71,27 @@ def _get_events(self):
         else:
             return None
 
+    def _get_current_events(self):
+        events_json = self.get_json(self.events[0])
+        if events_json:
+            return [x['$ref'] for x in events_json['items']]
+        else:
+            return None
+
+    def _get_current_matches(self):
+        matches = []
+        for match_url in self.current_events:
+            matches.append(Match(match_url.split("/events/")[-1]))
+        return matches
+
     def _build_events(self):
         events = []
         for event in self.events_json:
             events.append(self.get_json(event['$ref']))
         return events
+
+    def _build_matches(self):
+        matches = []
+        for match_url in self.events:
+            matches.append(Match(match_url.split("/events/")[-1]))
+        return matches
diff --git a/espncricinfo/teams.py b/espncricinfo/teams.py
new file mode 100644
index 0000000..4ed3e51
--- /dev/null
+++ b/espncricinfo/teams.py
@@ -0,0 +1,54 @@
+import json
+import requests
+from datetime import datetime
+from espncricinfo.exceptions import MatchNotFoundError, NoTeamError
+from espncricinfo.match import Match
+
+class Team:
+    def __init__(self, team_id, league_id=8081):
+        self.id = team_id
+        self.json_url = f"http://core.espnuk.org/v2/sports/cricket/leagues/{league_id}/teams/{series_id}/"
+        self.headers = {'user-agent': 'Mozilla/5.0'}
+        self.json = self.get_json(self.json_url)
+        
+        if self.json:
+            self.location = self.json.get('location')
+            self.name = self.json.get('name')
+            self.nickname = self.json.get('nickname')
+            self.short_name = self.json.get('abbreviation')
+            self.slug = self.json.get('slug')
+            self.color = self.json.get('color')
+            self.logo = next((logo.get("href") for logo in data.get("logos", []) if "href" in logo), None)
+            self.is_national = self.json.get('slug')
+            self.is_active = self.json.get('is_active')
+            self.match_date = self.parse_date(self.json.get('event').get('date'))
+            self._match_url = self.json.get('event').get('$ref')
+            self.match = Match(self.match_url.split("/events/")[-1])
+            self._players_url = self.json.get('athletes').get('$ref')
+            self._players = []
+    
+    @property
+    def players(self):
+        if not self._players:
+            from espncricinfo.player import Player
+            players_json = self.get_json(self._players_url)
+            if players_json:
+                player_urls = [x['$ref'] for x in players_json['items']]
+                for url in player_urls:
+                    player_ = Player(url.split("/athletes/")[-1])
+                    self._players.append(player_)
+        return self._players
+    
+    def get_json(self, url):
+        response = requests.get(url, headers=self.headers)
+        if response.status_code == 404:
+            raise NoTeamError("Season not found.")
+        return response.json()
+    
+    def parse_date(self, date_str):
+        if date_str:
+            return datetime.strptime(date_str, "%Y-%m-%dT%H:%MZ")
+        return None
+
+    def __repr__(self):
+        return f"Team({self.team_id}, {self.name}, {self.short_name})"