Skip to content

Off Ball Screens

The off_ball_screens section in the markings response contains a row for each off ball screen we identify in the tracking data.

Overview

An off ball screen occurs when an offensive player attempts to set a screen for a player who is not the ball handler.

Each row includes:

  • The key players involved (screener, cutter, and their defenders)
  • A start/end window around the screen action
  • The single frame where we consider the screen to have been closest to being set (screening_he_frame)
  • Additional detailed data about the screening action

A few important notes to be aware of:

  • Off ball screens are difficult to have both high precision (not having many incorrect labels) and high recall (not missing many true labels) because there is so much off ball movement that can look like a screening situation and there are many screening situations that might look a lot like normal off ball movement. If you want to include most true off ball screens, you end up getting a lot of noise. In this data set we have prioritized precision over recall, i.e. we try not to include off ball screens that are not true off ball screens if possible, even if that means missing a good chunk of true off ball screens.
  • We currently only include screens that occur when the screener is in the frontcourt and not further than 40 feet up the court than the ball. So this means that at this point, backcourt off ball screens or screens way up the court before the ball is in range are not included.
  • We also do not currently purposefully include players screening their own matchup. Ideally we would include them, but it is difficult to intentionally get those at this point without introducing a lot of noise. Some of these still do get included in the data set if the matchup flipped quickly and our system doesn't view the two players as matched up at some point during the screening action. But otherwise these situations will not be included in this data set.
  • If a screener goes to set a screen and the cutter does not use the screen, we aim to capture it in the data set but our hit rate on those is much lower. For example, here Duop Reath goes to set a screen in the right corner that is not used:
  • Sideline and baseline out of bounds situations present some weird situations, where a cutter might be moving past another player but that player is not obviously setting a screen, like Hauser here: In these cases, if it seems pretty clear that this is a screen-like action, we aim to include them as off ball screens even though a screen isn't truly set. But because of the lack of clear screening intent, these have a higher miss rate.
  • Similarly, there are cases where players are in a stack and cut off each other, for example, McCain curling off Yabusele here: Again, these often function like off ball screens and so we aim to include them even if the screener isn't truly setting a screen, but can have a higher miss rate because they don't look like classic screens.
  • Cases with clusters of players together or ambiguous matchup situations (for example when someone receives an off ball screen but then immediately turns and sets one for the same player) are quite difficult to handle properly. We sometimes properly include these in the data set but do not get the player being screened or the cutter correct. For example, in this situation, because of the way the players get clustered and defend the play, our model gets a bit confused. We currently include an off ball screen, but it has Duren screening Sarr:
  • One of our bigger sources of error is activity with a player in the dunker spot. There are cases where a player will be in the dunker and pin in a helping defender to open up a shooter in the corner, and cases where they are simply cutting down to the dunker, and both look very similar. For example, compare this action with Tobias Harris attempting to screen Trae Young (which we'd ideally want to count as an off ball screen): With this action where Brandon Clarke cuts down to the dunker and Anfernee Simons has to navigate around him (which we'd ideally not want to count as an off ball screen):

Sample Response

json
{
  "markings": {
    "off_ball_screens": [
        {
            "attacking_positive_x_basket": false,
            "chance_id_ctg": "chance_4a8ec3b4e4104a4cb6d9e2a5ec4fd2d0",
            "cutter_id_nba": 203458,
            "cutter_loc_x": -93.16,
            "cutter_loc_y": 18.86,
            "end_game_clock": 717.0,
            "end_he_frame": 422,
            "end_shot_clock": 22.0,
            "end_wall_clock": "2024-11-16T03:11:32.327+00:00",
            "game_id_nba": "0022400020",
            "off_ball_screen_id_ctg": "off_ball_screen_b345e475dcfd89192e28ff7a080d0eb4",
            "period": 1,
            "possession_id_ctg": "possession_8f26f2a75d0f4ad4a7c2dff39d8e8f6b",
            "screened_defender_id_nba": 203497,
            "screened_defender_loc_x": -107.28,
            "screened_defender_loc_y": -21.16,
            "screener_id_nba": 1628368,
            "screener_loc_x": -77.82,
            "screener_loc_y": 1.92,
            "screening_game_clock": 718.0,
            "screening_he_frame": 393,
            "screening_shot_clock": 23.0,
            "screening_wall_clock": "2024-11-16T03:11:31.844+00:00",
            "start_game_clock": 718.0,
            "start_he_frame": 393,
            "start_shot_clock": 23.0,
            "start_wall_clock": "2024-11-16T03:11:31.844+00:00"
        }
    ]
  }
}

Fields

Identifiers

off_ball_screen_id_ctg

Type: string

CTG-generated unique identifier for this off-ball screen event


game_id_nba

Type: string

NBA game ID


chance_id_ctg

Type: string | Nullable

CTG-generated identifier linking this off-ball screen to the chance in which it occurred.


possession_id_ctg

Type: string | Nullable

CTG-generated identifier linking this off-ball screen to the possession in which it occurred.


Players

screener_id_nba

Type: integer

NBA player ID of the offensive player setting the screen


cutter_id_nba

Type: integer

NBA player ID of the offensive player using the off-ball screen


screened_defender_id_nba

Type: integer

NBA player ID of the defender who is being screened


Location

attacking_positive_x_basket

Type: boolean

true if the offensive team is attacking the basket on the positive-x side of the court (i.e., the basket with positive x coordinates)


screener_loc_x

Type: float | Unit: inches

X coordinate of the screener's location at screening_he_frame


screener_loc_y

Type: float | Unit: inches

Y coordinate of the screener's location at screening_he_frame


cutter_loc_x

Type: float | Unit: inches

X coordinate of the cutter's location at screening_he_frame


cutter_loc_y

Type: float | Unit: inches

Y coordinate of the cutter's location at screening_he_frame


screened_defender_loc_x

Type: float | Unit: inches

X coordinate of the screened defender's location at screening_he_frame


screened_defender_loc_y

Type: float | Unit: inches

Y coordinate of the screened defender's location at screening_he_frame


Timing

period

Type: integer

Period number (1–4 for regulation, 5+ for overtime)


start_he_frame

Type: integer

Hawk-Eye frame number where the screen window begins.

The screen window is the contiguous frame span around screening_he_frame where:

  • The screener is relatively close their screening frame location
  • The screener is somewhat close to the screened defender
  • It is within 3 seconds of the screening frame

end_he_frame

Type: integer

Hawk-Eye frame number where the screen window ends (the last frame in the same window described in start_he_frame).


screening_he_frame

Type: integer

Hawk-Eye frame number that is our best guess for when the screen was initially set.


screening_game_clock

Type: float | Unit: seconds

Game clock (time remaining in the period) at screening_he_frame


screening_shot_clock

Type: float | Unit: seconds

Shot clock at screening_he_frame


screening_wall_clock

Type: string

UTC wall clock timestamp for screening_he_frame (ISO-8601)


start_game_clock

Type: float | Unit: seconds

Game clock (time remaining in the period) at start_he_frame


end_game_clock

Type: float | Unit: seconds

Game clock (time remaining in the period) at end_he_frame


start_shot_clock

Type: float | Unit: seconds

Shot clock at start_he_frame


end_shot_clock

Type: float | Unit: seconds

Shot clock at end_he_frame


start_wall_clock

Type: string

UTC wall clock timestamp for start_he_frame (ISO-8601)


end_wall_clock

Type: string

UTC wall clock timestamp for end_he_frame (ISO-8601)