Appearance
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": true,
"ballhandler_outcome": "shot",
"ballhandler_possession_touch_id": "possession_touch_fde352bc48b83cf13ba16b20f128f7d6",
"ballhandler_possession_touch_outcome_id": "shot_828453dbae99ddf663dbb1c7f9ac9f22",
"chance_id_ctg": "chance_6dda4f792e347155bb8d20ab207d75bd",
"cutter_id_nba": 1642843,
"cutter_loc_x": 184.46,
"cutter_loc_y": -115.87,
"drive_id": "drive_3481dfdc115e5b401fe2293886fe11e4",
"end_game_clock": 378.0,
"end_he_frame": 42966,
"end_shot_clock": 17.0,
"end_wall_clock": "2025-12-23T01:22:30.573+00:00",
"event_frame_number_he": null,
"event_type": null,
"game_id_nba": "0022500404",
"gap_defender_id": null,
"high_weak_side_defender_id": null,
"is_direct": false,
"cutter_touch_outcome_pass_to_screener": false,
"entry_pass_went_directly_to_screener": false,
"led_to_cutter_shot": false,
"led_to_cutter_touch": true,
"led_to_screener_shot": false,
"led_to_event": false,
"low_man_id": null,
"off_ball_screen_id_ctg": "off_ball_screen_407744444fc99966190ef8ea252749e5",
"off_ball_screen_type": "wide_pin_down",
"pbp_event_id": null,
"period": 1,
"possession_id_ctg": "possession_6dda4f792e347155bb8d20ab207d75bd",
"screened_defender_id_nba": 1630529,
"screened_defender_loc_x": 270.42,
"screened_defender_loc_y": -30.04,
"screener_defender_id_nba": 1642852,
"screener_id_nba": 203076,
"screener_loc_x": 270.62,
"screener_loc_y": 20.1,
"screening_game_clock": 378.0,
"screening_he_frame": 42941,
"screening_shot_clock": 18.0,
"screening_wall_clock": "2025-12-23T01:22:30.156+00:00",
"start_game_clock": 379.0,
"start_he_frame": 42886,
"start_shot_clock": 18.0,
"start_wall_clock": "2025-12-23T01:22:29.24+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.
Screen Type
off_ball_screen_type
Type: string
The type of off ball screen, based on where the players start and how they move.
wide_pin_down: A down screen for a cutter who starts in a corner or on the wing. The screener sets up in a way that is designed for the cutter to move up the court.other_pin_down: A down screen with the same basic shape as a wide pin down, but set closer to the middle of the court.out: A screen near the free throw line for the cutter to pop out from the middle of the court to a wing and get a clean catch.iverson: One or more screens near the free throw line elbows that are designed for the cutter to move across the top of the court with the ball in the middle of the court.flare: A screen that is set for the cutter to move away from the ball and toward a sideline that is notoutoriverson.pin_in: A screen for a cutter who stays mostly in place near the perimeter while the screener pins the defender in the interior.middle: A screen that helps the cutter move toward the ball or the middle of the court. This value includes actions like split and quick screening actions. It also is used for screens set during baseline out of bounds for the cutter to come off and more toward the baseline.back: A screen on the defender's back that helps the cutter move toward the basket. Wedge screens are included in this since the action is very similar.cross: A screen near the block designed for the cutter move into or across the lane.flex: A screen for a cutter who starts in the corner to go toward the rim.baseline_exit: A screen along the baseline designed for the cutter to move to a corner.zipper: A down screen before a sideline inbound pass that is designed for the cutter to come up the court to receive the ball.other: An off ball screen that does not match one of the listed types.
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
screener_defender_id_nba
Type: integer | Nullable
NBA player ID of the defender matched up to the screener at the time of the off-ball screen. null when the screener matchup is unavailable.
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)
is_direct
Type: boolean
true when the off-ball screen results in a direct scoring outcome for the cutter: the cutter shoots, is fouled and goes to the free throw line, or turns the ball over — or the cutter makes a final pass and the receiver shoots within one dribble of catching it (with no further passes before the shot). false otherwise.
led_to_event
Type: boolean
true when this off ball screen is deemed to have led to the chance ending event, such as a shot, turnover, foul, kicked ball, or jump ball. We say a off ball screen leads to an event when we think the screen was the main factor in the chance ending event: the defense doesn't reset after and the offense doesn't try to run a new action after the off ball screen.
event_type
Type: string | Nullable
The type of play by play event attributed to this off ball screen. This is null when led_to_event is false.
pbp_event_id
Type: integer | Nullable
Play-by-play event ID for the attributed play by play event. This is null when no play-by-play event is linked.
event_frame_number_he
Type: integer | Nullable
Hawk-Eye frame number for the attributed play by play event. This is null when led_to_event is false.
ballhandler_outcome
Type: string | Nullable
How the cutter's linked possession touch ended after the off-ball screen. One of: shot, pass, turnover, foul, violation, stoppage, unknown. null if the cutter did not receive the ball after the screen.
ballhandler_possession_touch_id
Type: string | Nullable
CTG-generated possession touch ID for the cutter touch linked to this off-ball screen. null if the cutter did not receive the ball after the screen.
ballhandler_possession_touch_outcome_id
Type: string | Nullable
CTG-generated event ID for how the linked cutter possession touch ended. This can be null when the outcome does not have a specific CTG event ID.
drive_id
Type: string | Nullable
CTG-generated drive ID for the earliest cutter drive that overlaps the linked possession touch after the screening frame. null if no such drive is identified.
Off-ball screen outcomes
led_to_cutter_touch
Type: boolean
true when the cutter receives a pass as a direct outcome of this off ball screen. If the pass reception does not seem to have come from the screen or there is another later off ball screen for this cutter before the pass, this will be false.
led_to_cutter_shot
Type: boolean
true when the cutter received a pass as a direct outcome of this off ball screen and their touch ended in a shot within a reasonable amount of time. If the pass reception does not seem to have come from the screen or there is another later off ball screen for this cutter before the pass, this will be false. If there is a ball screen after the touch start, then the shot would not be counted as coming from the off ball screen and this would be false.
entry_pass_went_directly_to_screener
Type: boolean
true when the first pass created by the screening action is received by the screener. If the pass reception does not seem to have come from the screen or there is another later screen involving this pass receiver before the pass, this will be false.
led_to_screener_shot
Type: boolean
true when entry_pass_went_directly_to_screener is true and that player's touch led to a shot in a reasonable amount of time and with not screens for the player in between.
cutter_touch_outcome_pass_to_screener
Type: boolean
true when led_to_cutter_touch is true and the cutter made a pass intended for the original screener.
Off-ball context fields
gap_defender_id
Type: integer | Nullable
NBA player ID of the defender who is on the strong side, is guarding a player who is one pass away, and is not guarding a player in the corner. null if no such defender is identified on this play.
high_weak_side_defender_id
Type: integer | Nullable
NBA player ID of the defender identified as the highest weak-side defender when more than one weak-side defender is present. null if no such defender is identified on this play.
low_man_id
Type: integer | Nullable
NBA player ID of the defender estimated to have low-man responsibility at off-ball screen start (typically the lowest weak-side defender, or the lowest strong-side defender when there are no weak-side defenders). null if no such defender is identified on this play.
