Dec 16, 2025

Convert Revit Coordinates with Revit API [Internal, Project, Survey]

Learn how to convert XYZ Coordinates in Revit API.

Coordinate Systems in Revit

Revit Coordinate Systems is a tricky topic!
Especially if you want to automate coordinates with Revit APIโ€ฆ

In Revit API you need to be careful with units that you use.
Because It's so easy to use the wrong units
and then spend hours looking for an issueโ€ฆ.
(Yeahโ€ฆ I've been there multiple times)

But don't worry,
I already did the hard work for you!

It took me couple of days,
but now I have my own Coordinate Converter
than anyone can use in in 3 lines of code.
Yeahโ€ฆ It's that simple.

And the best part?
I'm going to share it with you in a moment for FREE.
It will literally save you days of headache

All you'll have to do:

  • Copy my code

  • Understand 3 lines on how to use it

  • And enjoy the simplicity of working with coordinates

But before I share my grand solutionโ€ฆ
Let's have a quick overview of coordinate systems in Revit.

Coordinate Systems Overview

There are 3 Coordinate Systems in Revit:

  • Internal (Used as the internal system of Revit, used in Revit API)

  • Project (Based on Project Base Point)

  • Survey (Based on Survey Point)

Also keep in mind that in Revit we can set True North rotation, which will not affect all systems similar.

  • Internal - True North Rotation is not applied

  • Project - True North Rotation is not applied

  • Survey - All coordinates will be affected by True North Rotation.  


๐Ÿ’กPro Tip

Before you beginโ€ฆ
I really recommend creating proper tags to easily read correct values.,

It can easily help you avoid using the wrong units or data as you create your custom tools.

You can also push it a step further
and create tags for both:

  • Metric Units

  • Internal Units

This way you'll instantly notice if you're exporting the wrong data.
(Trust me, it happens way too often with coordinates when we use APIโ€ฆ)

Alright and now - let's look into API


Revit Coordinates in Revit API

First of all you need to know that Revit API always uses Internal Coordinate System in feet.

That means that when you read XYZ values, you'll get them in Internal System in Feet.
And it also means that you need to prepare your XYZ values in Internal System in Feet.

And if you forget this, don't be surprised when your
elements are flying in the sky above your project.

Now let's look at how to convert coordinates with Code.


My Coordinate Converter Class

I've prepared a custom class that can convert XYZ points from any
coorindate system into any other with just a few lines.

๐ŸšจANd Spoiler alert: you're about to see code that might scare many of you.
But you don't even have to understand anything about it.

๐Ÿ‘‰ You just copy the code below.
๐Ÿ‘‰ Paste in your script
๐Ÿ‘‰ Scroll to next example to undrstand how to use it


# โ•ฆโ•”โ•ฆโ•—โ•”โ•โ•—โ•”โ•โ•—โ•ฆโ•โ•—โ•”โ•ฆโ•—โ•”โ•โ•—
# โ•‘โ•‘โ•‘โ•‘โ• โ•โ•โ•‘ โ•‘โ• โ•ฆโ• โ•‘ โ•šโ•โ•—
# โ•ฉโ•ฉ โ•ฉโ•ฉ  โ•šโ•โ•โ•ฉโ•šโ• โ•ฉ โ•šโ•โ•
#==================================================
from Autodesk.Revit.DB import *

# โ•ฆ  โ•ฆโ•”โ•โ•—โ•ฆโ•โ•—โ•ฆโ•”โ•โ•—โ•”โ•— โ•ฆ  โ•”โ•โ•—โ•”โ•โ•—
# โ•šโ•—โ•”โ•โ• โ•โ•ฃโ• โ•ฆโ•โ•‘โ• โ•โ•ฃโ• โ•ฉโ•—โ•‘  โ•‘โ•ฃ โ•šโ•โ•—
#  โ•šโ• โ•ฉ โ•ฉโ•ฉโ•šโ•โ•ฉโ•ฉ โ•ฉโ•šโ•โ•โ•ฉโ•โ•โ•šโ•โ•โ•šโ•โ•
#==================================================
uidoc  = __revit__.ActiveUIDocument
doc    = __revit__.ActiveUIDocument.Document #type:Document


# โ•”โ•โ•—โ•ฆ  โ•”โ•โ•—โ•”โ•โ•—โ•”โ•โ•—
# โ•‘  โ•‘  โ• โ•โ•ฃโ•šโ•โ•—โ•šโ•โ•—
# โ•šโ•โ•โ•ฉโ•โ•โ•ฉ โ•ฉโ•šโ•โ•โ•šโ•โ•
#==================================================
class CoordSys:
    Internal = 'Internal'
    Project  = 'Project'
    Survey   = 'Survey'

class PointConverter:
    pt_internal = None
    pt_survey   = None
    pt_project  = None

    def __init__(self, input_pt, coord_sys=CoordSys.Internal):
        """Converte 2.0 for converting XYZ points between any Coordinate Systems.
        Args:
            :param input_pt: The XYZ point in Internal Coordinate System. Adjust coord_sys argument if you want to use other Cooridnate Systems.
            :param coord_sys: The coordinate system chosen from CoordSys helper class (Internal, Project, Survey)
            
        Example:
            pt = elem.Location.Point
            
            converter   = PointConverter(pt, CoordSys.Internal)
            pt_survey   = pt_converter.pt_survey   # XYZ in FEET 
            pt_survey_m = pt_converter.pt_survey_m # XYZ in Meters
           
            pt_converter.print_in_metric(coord_sys=CoordSys.Survey)    
        """
        # type: float, float, float, CoordSys

        # Get Systems Transform
        srvTrans  = self._GetSurveyTransform()
        projTrans = self._GetProjectTransform()

        #1๏ธโƒฃ INPUT - INTERNAL COORDINATE SYSTEM
        if coord_sys == CoordSys.Internal:
            self.pt_internal = input_pt
            self.pt_survey   = self._ApplyInverseTransformation(srvTrans, self.pt_internal)
            self.pt_project  = self._ApplyInverseTransformation(projTrans, self.pt_internal)

        #2๏ธโƒฃ INPUT -  PROJECT COORDINATE SYSTEM
        elif coord_sys == CoordSys.Project:
            self.pt_project  = input_pt
            self.pt_internal = self._ApplyTransformation(projTrans, self.pt_project)
            self.pt_survey   = self._ApplyInverseTransformation(srvTrans, self.pt_internal)

        #3๏ธโƒฃ - SURVEY COORDINATE SYSTEM
        elif coord_sys == CoordSys.Survey:
            self.pt_survey   = input_pt
            self.pt_internal = self._ApplyTransformation(srvTrans, self.pt_survey)
            self.pt_project  = self._ApplyInverseTransformation(projTrans, self.pt_internal)

        else:
            raise Exception("Wrong argument value for 'coord_sys' in PointConverter class.")


        #๐Ÿงฎ Create Metric Points
        self.pt_internal_m = self._get_metric_XYZ(CoordSys.Internal)
        self.pt_project_m   = self._get_metric_XYZ(CoordSys.Project)
        self.pt_survey_m   = self._get_metric_XYZ(CoordSys.Survey)


    def print_in_metric(self, coord_sys, units=UnitTypeId.Meters):
        """ Helper function to display coordinates in Metric System."""
        pt_m = self._get_metric_XYZ(coord_sys, units)
        print('[{}] XYZ: ({}m, {}m, {}m)'.format(coord_sys, pt_m.X, pt_m.Y, pt_m.Z))


    #๐Ÿšง INTERNAL HELPING METHODS
    def _get_metric_XYZ(self, coord_sys, units=UnitTypeId.Meters):
        """Convert the point into Metric XYZ System.
        NB! Do not use it with Revit API as it needs internal units."""
        # Get Point With Correct Coordinate System
        if coord_sys == CoordSys.Internal:  pt = self.pt_internal
        elif coord_sys == CoordSys.Project: pt = self.pt_project
        elif coord_sys == CoordSys.Survey:  pt = self.pt_survey

        # Convert Values to Metric
        X_m = UnitUtils.ConvertFromInternalUnits(pt.X, units)
        Y_m = UnitUtils.ConvertFromInternalUnits(pt.Y, units)
        Z_m = UnitUtils.ConvertFromInternalUnits(pt.Z, units)

        return (XYZ(X_m, Y_m, Z_m))

    def _GetSurveyTransform(self):
        """Gets the Active Project Locations Transform (Survey)."""
        return doc.ActiveProjectLocation.GetTotalTransform()

    def _GetProjectTransform(self):
        """Get the Project Base Points Transform."""
        basePtLoc = next((l for l in FilteredElementCollector(doc) \
                          .OfClass(ProjectLocation) \
                          .WhereElementIsNotElementType() \
                          .ToElements() if l.Name == "Project"), None)
        return basePtLoc.GetTotalTransform()

    def _ApplyInverseTransformation(self, t, pt):
        """Applies the inverse transformation of
        the given Transform to the given point."""
        return t.Inverse.OfPoint(pt)

    def _ApplyTransformation(self, t, pt):
        """Applies the transformation of
        the given Transform to the given point."""
        return t.OfPoint(pt)


๐Ÿค”How to use it?

And now, here's the gravy for your fries.

As I mentioned:
You don't even need to understand the class I provided.
You just need to use a few methods.

๐Ÿ’กAnd please pay attention to units that you use !


And here's an example:
Where I'll take a list of generic models ('EF_Box')
And I'm going to convert internal coordinates into Project and Survey Systems.

# Get Elements
elems = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericModel).WhereElementIsNotElementType().ToElements()
boxes = [e for e in elems if 'EF_Box' in e.Name] # โš ๏ธ I use specific Type Name to filter...

# Get Coordinates
for box in boxes:
    # Get Location
    pt     = box.Location.Point # Internal Coordinate System (defualt)

    # ๐Ÿ‘‰ Convert XYZ Point 
    pt_converter = PointConverter(pt, CoordSys.Internal)
  
    pt_survey    = pt_converter.pt_survey    # XYZ - SURVEY WITH VALUES IN FEET
    pt_survey_m  = pt_converter.pt_survey_m  # XYZ - SURVEY WITH VALUES IN METERS 

    pt_project   = pt_converter.pt_project   # XYZ - PROJECT WITH VALUES IN FEET
    pt_project_m = pt_converter.pt_project_m # XYZ - PROJECT WITH VALUES IN METERS 
  

    # Extra Function To Print Correct Data Display Results
    pt_converter.print_in_metric(coord_sys=CoordSys.Survey)

Simple right?

As you can see I've used XYZ with internal coordinates to create Survey and Project coordinates.
But I could also import some excel data of Survey coordinates, and convert it back into internalโ€ฆ

You get the point.

Enjoy working with Revit API Coordinates like a Pro.
Feel free to mention this article to others coders!
They'll love you for that.

Happy Coding.


Join Newsletter

๐Ÿ“ฉ You will be added to Revit API Newsletter

Join Us!

which is already read by 9500+ people!

Ready to become Revit Hero for your office? Learn Revit API!

Join this comprehensive course that will guide you step by step on how to create your dream tools for Revit that save time.