diff --git a/README.md b/README.md
index c9466ae..9832a00 100644
--- a/README.md
+++ b/README.md
@@ -259,6 +259,12 @@ Official Documentation: [VisitorActivities](http://developer.pardot.com/kb/api-v
 - Query
 - Read
 
+### Visits
+Official Documentation: [Visits](https://developer.pardot.com/kb/api-version-3/visits/)
+
+- Query
+- Read
+
 ## How to Contribute 
 
 Want to help implement the missing API end points?  Fork the repository, write some code, and 
diff --git a/src/main/java/com/darksci/pardot/api/PardotClient.java b/src/main/java/com/darksci/pardot/api/PardotClient.java
index ff8ef7b..759d903 100644
--- a/src/main/java/com/darksci/pardot/api/PardotClient.java
+++ b/src/main/java/com/darksci/pardot/api/PardotClient.java
@@ -58,6 +58,8 @@
 import com.darksci.pardot.api.parser.user.UserCreateResponseParser;
 import com.darksci.pardot.api.parser.user.UserQueryResponseParser;
 import com.darksci.pardot.api.parser.user.UserReadResponseParser;
+import com.darksci.pardot.api.parser.visit.VisitQueryResponseParser;
+import com.darksci.pardot.api.parser.visit.VisitReadResponseParser;
 import com.darksci.pardot.api.parser.visitor.VisitorQueryResponseParser;
 import com.darksci.pardot.api.parser.visitor.VisitorReadResponseParser;
 import com.darksci.pardot.api.parser.visitoractivity.VisitorActivityQueryResponseParser;
@@ -127,6 +129,8 @@
 import com.darksci.pardot.api.request.user.UserQueryRequest;
 import com.darksci.pardot.api.request.user.UserReadRequest;
 import com.darksci.pardot.api.request.user.UserUpdateRoleRequest;
+import com.darksci.pardot.api.request.visit.VisitQueryRequest;
+import com.darksci.pardot.api.request.visit.VisitReadRequest;
 import com.darksci.pardot.api.request.visitor.VisitorAssignRequest;
 import com.darksci.pardot.api.request.visitor.VisitorQueryRequest;
 import com.darksci.pardot.api.request.visitor.VisitorReadRequest;
@@ -170,6 +174,8 @@
 import com.darksci.pardot.api.response.user.User;
 import com.darksci.pardot.api.response.user.UserAbilitiesResponse;
 import com.darksci.pardot.api.response.user.UserQueryResponse;
+import com.darksci.pardot.api.response.visit.Visit;
+import com.darksci.pardot.api.response.visit.VisitQueryResponse;
 import com.darksci.pardot.api.response.visitor.Visitor;
 import com.darksci.pardot.api.response.visitor.VisitorQueryResponse;
 import com.darksci.pardot.api.response.visitoractivity.VisitorActivity;
@@ -1127,6 +1133,28 @@ public Optional<VisitorActivity> visitorActivityRead(final VisitorActivityReadRe
         );
     }
 
+    /**
+     * Make API request to query visits.
+     * @param request Request definition.
+     * @return Parsed api response.
+     */
+    public VisitQueryResponse.Result visitQuery(final VisitQueryRequest request) {
+        return submitRequest(request, new VisitQueryResponseParser())
+                .orElseThrowInvalidRequestException();
+    }
+
+    /**
+     * Make API request to read a visit.
+     * @param request Request definition.
+     * @return Parsed api response
+     */
+    public Optional<Visit> visitRead(final VisitReadRequest request) {
+        return optionalUnlessErrorCode(
+                submitRequest(request, new VisitReadResponseParser()),
+                ErrorCode.INVALID_ID, ErrorCode.INVALID_VISIT_ID
+        );
+    }
+
     /**
      * Entry point for adhoc user defined requests.
      *
diff --git a/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java b/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java
new file mode 100644
index 0000000..14a92cf
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.parser.visit;
+
+import com.darksci.pardot.api.parser.JacksonFactory;
+import com.darksci.pardot.api.parser.ResponseParser;
+import com.darksci.pardot.api.response.visit.VisitQueryResponse;
+
+import java.io.IOException;
+
+/**
+ * Handles parsing Visit Query API responses into POJOs.
+ */
+public class VisitQueryResponseParser implements ResponseParser<VisitQueryResponse.Result> {
+
+    @Override
+    public VisitQueryResponse.Result parseResponse(final String responseStr) throws IOException {
+        return JacksonFactory.newInstance().readValue(responseStr, VisitQueryResponse.class).getResult();
+    }
+}
diff --git a/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java b/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java
new file mode 100644
index 0000000..ac27d1a
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.parser.visit;
+
+import com.darksci.pardot.api.parser.JacksonFactory;
+import com.darksci.pardot.api.parser.ResponseParser;
+import com.darksci.pardot.api.response.visit.Visit;
+import com.darksci.pardot.api.response.visit.VisitReadResponse;
+
+import java.io.IOException;
+
+/**
+ * Handles parsing Visit Read API responses into POJOs.
+ */
+public class VisitReadResponseParser implements ResponseParser<Visit> {
+
+    @Override
+    public Visit parseResponse(final String responseStr) throws IOException {
+        return JacksonFactory.newInstance().readValue(responseStr, VisitReadResponse.class).getVisit();
+    }
+}
diff --git a/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java b/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java
new file mode 100644
index 0000000..e31bce0
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.request.visit;
+
+import com.darksci.pardot.api.request.BaseQueryRequest;
+
+import java.util.Collection;
+
+/**
+ * Defines a Visit Query Request.
+ */
+public class VisitQueryRequest extends BaseQueryRequest<VisitQueryRequest> {
+
+    @Override
+    public String getApiEndpoint() {
+        return "visit/do/query";
+    }
+
+    // Filter Options
+
+    /**
+     * Only select visits who are associated with the specified visit id.
+     * @param id The visit id to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withId(final Long id) {
+        return withCollectionParam("ids", id);
+    }
+
+    /**
+     * Only select visits who are associated with the specified visit ids.
+     * @param ids The visit ids to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withIds(final Collection<Long> ids) {
+        return withCollectionParams("ids", ids);
+    }
+
+    /**
+     * Only select visits who are associated with the specified visitor id.
+     * @param visitorId The visitor id to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withVisitorId(final Long visitorId) {
+        return withCollectionParam("visitor_ids", visitorId);
+    }
+
+    /**
+     * Only select visits who are associated with the specified visitor ids.
+     * @param visitorIds The visitor ids to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withVisitorIds(final Collection<Long> visitorIds) {
+        return withCollectionParams("visitor_ids", visitorIds);
+    }
+
+    /**
+     * Only select visits who are associated with the specified prospect id.
+     * @param prospectId The prospect id to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withProspectId(final Long prospectId) {
+        return withCollectionParam("prospect_ids", prospectId);
+    }
+
+    /**
+     * Only select visits who are associated with the specified prospect ids.
+     * @param prospectIds The prospect ids to filter by.
+     * @return RequestBuilder
+     */
+    public VisitQueryRequest withProspectIds(final Collection<Long> prospectIds) {
+        return withCollectionParams("prospect_ids", prospectIds);
+    }
+
+
+}
diff --git a/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java b/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java
new file mode 100644
index 0000000..0f61c35
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.request.visit;
+
+import com.darksci.pardot.api.request.BaseRequest;
+
+/**
+ * Used to generate a Visit read request.
+ */
+public class VisitReadRequest extends BaseRequest<VisitReadRequest> {
+
+    @Override
+    public String getApiEndpoint() {
+        return "visit/do/read";
+    }
+
+    /**
+     * Returns the data for the visit specified by id.
+     * @param id The Id of the target visit.
+     * @return VisitReadRequest builder.
+     */
+    public VisitReadRequest selectById(final Long id) {
+        return setParam("id", id);
+    }
+}
diff --git a/src/main/java/com/darksci/pardot/api/response/ErrorCode.java b/src/main/java/com/darksci/pardot/api/response/ErrorCode.java
index f83f948..32be61a 100644
--- a/src/main/java/com/darksci/pardot/api/response/ErrorCode.java
+++ b/src/main/java/com/darksci/pardot/api/response/ErrorCode.java
@@ -37,6 +37,7 @@ public enum ErrorCode {
     INVALID_VISITOR_ID(24),
     INVALID_OPPORTUNITY_ID(35),
     INVALID_CAMPAIGN_ID(38),
+    INVALID_VISIT_ID(48),
     EMAIL_ADDRESS_IS_ALREADY_IN_USE(54),
     INVALID_LIST_ID(55),
     INVALID_EMAIL_FORMAT(65),
diff --git a/src/main/java/com/darksci/pardot/api/response/visit/Visit.java b/src/main/java/com/darksci/pardot/api/response/visit/Visit.java
new file mode 100644
index 0000000..ae4bbcb
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/response/visit/Visit.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.response.visit;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import org.joda.time.LocalDateTime;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a Pardot visit.
+ */
+public class Visit {
+    private Long id;
+    private Long visitorId;
+    private Long prospectId;
+    private Integer visitorPageViewCount;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime firstVisitorPageViewAt;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime lastVisitorPageViewAt;
+    private Integer durationInSeconds;
+    private String campaignParameter;
+    private String mediumParameter;
+    private String sourceParameter;
+    private String contentParameter;
+    private String termParameter;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createdAt;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updatedAt;
+
+    @JacksonXmlElementWrapper(localName = "visitor_page_views")
+    private List<VisitorPageView> visitorPageViews;
+
+    public Long getId() { return id; }
+
+    public Long getVisitorId() { return visitorId; }
+
+    public Long getProspectId() { return prospectId; }
+
+    public Integer getVisitorPageViewCount() { return visitorPageViewCount; }
+
+    public LocalDateTime getFirstVisitorPageViewAt() { return firstVisitorPageViewAt; }
+
+    public LocalDateTime getLastVisitorPageViewAt() { return lastVisitorPageViewAt; }
+
+    public Integer getDurationInSeconds() { return durationInSeconds; }
+
+    public String getCampaignParameter() { return campaignParameter; }
+
+    public String getMediumParameter() { return mediumParameter; }
+
+    public String getSourceParameter() { return sourceParameter; }
+
+    public String getContentParameter() { return contentParameter; }
+
+    public String getTermParameter() { return termParameter; }
+
+    public LocalDateTime getCreatedAt() { return createdAt; }
+
+    public LocalDateTime getUpdatedAt() { return updatedAt; }
+
+    /**
+     * Visitor Page Views associated to the visit, or empty list if none.
+     *
+     * @return Associated Visitor Page Views, or empty list if none.
+     */
+    public List<VisitorPageView> getVisitorPageViews() {
+        if (visitorPageViews == null) {
+            return new ArrayList<>();
+        }
+        return visitorPageViews;
+    }
+
+    @Override
+    public String toString() {
+        return "Visitor{"
+            + "id=" + id
+            + ", visitorId=" + visitorId
+            + ", prospectId=" + prospectId
+            + ", visitorPageViewCount=" + visitorPageViewCount
+            + ", firstVisitorPageViewAt=" + firstVisitorPageViewAt
+            + ", lastVisitorPageViewAt=" + lastVisitorPageViewAt
+            + ", durationInSeconds=" + durationInSeconds
+            + ", campaignParameter='" + campaignParameter + '\''
+            + ", mediumParameter='" + mediumParameter + '\''
+            + ", sourceParameter='" + sourceParameter + '\''
+            + ", contentParameter='" + contentParameter + '\''
+            + ", termParameter='" + termParameter + '\''
+            + ", createdAt=" + createdAt
+            + ", updatedAt=" + updatedAt
+            + '}';
+    }
+}
diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java
new file mode 100644
index 0000000..5806ade
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.response.visit;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents the result from a Visit Query API call.
+ */
+public class VisitQueryResponse {
+    private Result result;
+
+    public Result getResult() {
+        return result;
+    }
+
+    /**
+     * Represents one or more visitors.
+     */
+    public static class Result {
+        private Integer totalResults = 0;
+
+        @JacksonXmlProperty(localName = "visit")
+        private List<Visit> visits = Collections.emptyList();
+
+        public Integer getTotalResults() {
+            return totalResults;
+        }
+
+        /**
+         * Visits returned by the API.
+         *
+         * @return Visit results.
+         */
+        public List<Visit> getVisits() {
+            if (visits == null) {
+                visits = Collections.emptyList();
+            }
+            return Collections.unmodifiableList(visits);
+        }
+
+        @Override
+        public String toString() {
+            return "Result{"
+                + "totalResults=" + totalResults
+                + ", visits=" + visits
+                + '}';
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "VisitQueryResponse{"
+            + "result=" + result
+            + '}';
+    }
+}
diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java
new file mode 100644
index 0000000..ec14f18
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.response.visit;
+
+/**
+ * Represents a Pardot Visit.
+ */
+public class VisitReadResponse {
+
+    private Visit visit;
+
+    public Visit getVisit() { return visit; }
+}
diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java
new file mode 100644
index 0000000..4534994
--- /dev/null
+++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.response.visit;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.joda.time.LocalDateTime;
+
+/**
+ * Represents Visitor Page View on a Pardot Visit.
+ */
+public class VisitorPageView {
+    private Long id;
+    private String url;
+    private String title;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createdAt;
+
+    public Long getId() { return id; }
+
+    public String getUrl() { return url; }
+
+    public String getTitle() { return title; }
+
+    public LocalDateTime getCreatedAt() { return createdAt; }
+
+    @Override
+    public String toString() {
+        return "VisitorPageView{"
+            + "id=" + id
+            + ", replyToAddress='" + url + '\''
+            + ", sendFromData='" + title + '\''
+            + ", createdAt=" + createdAt
+            + '}';
+    }
+}
diff --git a/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java b/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java
index bce6a04..adb97fd 100644
--- a/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java
+++ b/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java
@@ -77,6 +77,8 @@
 import com.darksci.pardot.api.request.user.UserQueryRequest;
 import com.darksci.pardot.api.request.user.UserReadRequest;
 import com.darksci.pardot.api.request.user.UserUpdateRoleRequest;
+import com.darksci.pardot.api.request.visit.VisitQueryRequest;
+import com.darksci.pardot.api.request.visit.VisitReadRequest;
 import com.darksci.pardot.api.request.visitor.VisitorAssignRequest;
 import com.darksci.pardot.api.request.visitor.VisitorQueryRequest;
 import com.darksci.pardot.api.request.visitor.VisitorReadRequest;
@@ -116,6 +118,8 @@
 import com.darksci.pardot.api.response.user.User;
 import com.darksci.pardot.api.response.user.UserAbilitiesResponse;
 import com.darksci.pardot.api.response.user.UserQueryResponse;
+import com.darksci.pardot.api.response.visit.Visit;
+import com.darksci.pardot.api.response.visit.VisitQueryResponse;
 import com.darksci.pardot.api.response.visitor.Visitor;
 import com.darksci.pardot.api.response.visitor.VisitorQueryResponse;
 import com.darksci.pardot.api.response.visitoractivity.VisitorActivity;
@@ -1387,4 +1391,28 @@ public void visitorActivityReadTest() {
         assertNotNull("Should not be null", response);
         logger.info("Response: {}", response);
     }
+
+    /**
+     * Test Querying visits.
+     */
+    public void visitQueryTest() {
+        final long visitId = 1L;
+        final VisitQueryRequest request = new VisitQueryRequest().withId(visitId);
+
+        final VisitQueryResponse.Result response = client.visitQuery(request);
+        assertNotNull("Should not be null", response);
+        logger.info("Response: {}", response);
+    }
+
+    /**
+     * Test Reading a visit.
+     */
+    public void visitReadTest() {
+        final long visitId = 1L;
+        final VisitReadRequest request = new VisitReadRequest().selectById(visitId);
+
+        final Optional<Visit> response = client.visitRead(request);
+        assertNotNull("Should not be null", response);
+        logger.info("Response: {}", response);
+    }
 }
diff --git a/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java b/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java
index a0d5695..b1e47d5 100644
--- a/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java
+++ b/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java
@@ -539,4 +539,16 @@ public void visitorActivityQueryTest() {
     public void visitorActivityReadTest() {
         super.visitorActivityReadTest();
     }
+
+    @Test
+    @Override
+    public void visitQueryTest() {
+        super.visitQueryTest();
+    }
+
+    @Test
+    @Override
+    public void visitReadTest() {
+        super.visitReadTest();
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java b/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java
index 9d53af6..7173dd8 100644
--- a/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java
+++ b/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java
@@ -547,4 +547,12 @@ public void visitorActivityQueryTest() {
     public void visitorActivityReadTest() {
         super.visitorActivityReadTest();
     }
+
+    @Test
+    @Override
+    public void visitQueryTest() { super.visitQueryTest(); }
+
+    @Test
+    @Override
+    public void visitReadTest() { super.visitReadTest(); }
 }
diff --git a/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java b/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java
new file mode 100644
index 0000000..39a5e46
--- /dev/null
+++ b/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.parser.visit;
+
+import com.darksci.pardot.api.parser.BaseResponseParserTest;
+import com.darksci.pardot.api.response.visit.Visit;
+import com.darksci.pardot.api.response.visit.VisitQueryResponse;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class VisitQueryResponseParserTest extends BaseResponseParserTest {
+    private static final Logger logger = LoggerFactory.getLogger(VisitQueryResponseParserTest.class);
+
+    /**
+     * Validates we can parse a Visit query with multiple visitors response A-OK.
+     */
+    @Test
+    public void testMultpleVisits() throws IOException {
+        final String input = readFile("visitQuery.xml");
+        final VisitQueryResponse.Result response = new VisitQueryResponseParser().parseResponse(input);
+        logger.info("Result: {}", response);
+
+        assertNotNull("Should not be null", response);
+        assertEquals("Should have 2 results", 2, (int) response.getTotalResults());
+        assertEquals("Should have 2 results", 2, response.getVisits().size());
+        validateVisit1(response.getVisits().get(0));
+        validateVisit2(response.getVisits().get(1));
+    }
+
+    private void validateVisit1(final Visit visit) {
+        assertEquals("Has correct id", 37640L, (long) visit.getId());
+        assertEquals("Has correct visitorId", 123L, (long) visit.getVisitorId());
+        assertEquals("Has correct prospectId", 123L, (long) visit.getProspectId());
+        assertEquals("Has correct visitorPageViewCount", 1024, (int) visit.getVisitorPageViewCount());
+        assertEquals("Has correct firstVisitorPageViewAt", "2015-09-03T11:57:01.000", visit.getFirstVisitorPageViewAt().toString());
+        assertEquals("Has correct lastVisitorPageViewAt", "2015-09-03T11:57:24.000", visit.getLastVisitorPageViewAt().toString());
+        assertEquals("Has correct durationInSeconds", 1024, (int) visit.getDurationInSeconds());
+        assertEquals("Has correct campaign parameter", "Campaign Parameter", visit.getCampaignParameter());
+        assertEquals("Has correct medium parameter", "Medium Parameter", visit.getMediumParameter());
+        assertEquals("Has correct Source parameter", "Source Parameter", visit.getSourceParameter());
+        assertEquals("Has correct Content parameter", "Content Parameter", visit.getContentParameter());
+        assertEquals("Has correct Term parameter", "Term Parameter", visit.getTermParameter());
+        assertEquals("Has correct createdAt", "2015-09-03T11:57:01.000", visit.getCreatedAt().toString());
+        assertEquals("Has correct updatedAt", "2015-09-03T11:57:24.000", visit.getUpdatedAt().toString());
+    }
+
+    private void validateVisit2(final Visit visit) {
+        assertEquals("Has correct id", 37641L, (long) visit.getId());
+        assertNull("Field is null", visit.getVisitorId());
+        assertNull("Field is null", visit.getProspectId());
+        assertNull("Field is null", visit.getVisitorPageViewCount());
+        assertNull("Field is null", visit.getFirstVisitorPageViewAt());
+        assertNull("Field is null", visit.getLastVisitorPageViewAt());
+        assertNull("Field is null", visit.getDurationInSeconds());
+        assertNull("Field is null", visit.getCampaignParameter());
+        assertNull("Field is null", visit.getMediumParameter());
+        assertNull("Field is null", visit.getSourceParameter());
+        assertNull("Field is null", visit.getContentParameter());
+        assertNull("Field is null", visit.getTermParameter());
+        assertEquals("Has correct createdAt", "2015-10-03T11:57:01.000", visit.getCreatedAt().toString());
+        assertEquals("Has correct updatedAt", "2015-10-03T11:57:24.000", visit.getUpdatedAt().toString());
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java b/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java
new file mode 100644
index 0000000..6507326
--- /dev/null
+++ b/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.darksci.pardot.api.parser.visit;
+
+import com.darksci.pardot.api.parser.BaseResponseParserTest;
+import com.darksci.pardot.api.response.visit.Visit;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class VisitReadResponseResponseParserTest extends BaseResponseParserTest {
+    private static final Logger logger = LoggerFactory.getLogger(VisitReadResponseResponseParserTest.class);
+
+    /**
+     * Validates we can parse a Visit Read
+     */
+    @Test
+    public void testRead() throws IOException {
+        final String input = readFile("visitRead.xml");
+        final Visit visit = new VisitReadResponseParser().parseResponse(input);
+        logger.info("Result: {}", visit);
+
+        assertNotNull("Has non null response", visit);
+        validateVisit1(visit);
+    }
+
+    private void validateVisit1(final Visit visit) {
+        assertEquals("Has correct id", 37640L, (long) visit.getId());
+        assertEquals("Has correct visitorId", 123L, (long) visit.getVisitorId());
+        assertEquals("Has correct prospectId", 123L, (long) visit.getProspectId());
+        assertEquals("Has correct visitorPageViewCount", 1024, (int) visit.getVisitorPageViewCount());
+        assertEquals("Has correct firstVisitorPageViewAt", "2015-09-03T11:57:01.000", visit.getFirstVisitorPageViewAt().toString());
+        assertEquals("Has correct lastVisitorPageViewAt", "2015-09-03T11:57:24.000", visit.getLastVisitorPageViewAt().toString());
+        assertEquals("Has correct durationInSeconds", 1024, (int) visit.getDurationInSeconds());
+        assertEquals("Has correct campaign parameter", "Campaign Parameter", visit.getCampaignParameter());
+        assertEquals("Has correct medium parameter", "Medium Parameter", visit.getMediumParameter());
+        assertEquals("Has correct Source parameter", "Source Parameter", visit.getSourceParameter());
+        assertEquals("Has correct Content parameter", "Content Parameter", visit.getContentParameter());
+        assertEquals("Has correct Term parameter", "Term Parameter", visit.getTermParameter());
+        assertEquals("Has correct createdAt", "2015-09-03T11:57:01.000", visit.getCreatedAt().toString());
+        assertEquals("Has correct updatedAt", "2015-09-03T11:57:24.000", visit.getUpdatedAt().toString());
+        assertFalse("Should NOT have empty visitor page view list", visit.getVisitorPageViews().isEmpty());
+        assertEquals("Should have 2 visitor page views", 2, visit.getVisitorPageViews().size());
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/mockResponses/visitQuery.xml b/src/test/resources/mockResponses/visitQuery.xml
new file mode 100644
index 0000000..95befe3
--- /dev/null
+++ b/src/test/resources/mockResponses/visitQuery.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rsp stat="ok" version="1.0">
+    <result>
+        <total_results>2</total_results>
+        <visit>
+            <id>37640</id>
+            <visitor_id>123</visitor_id>
+            <prospect_id>123</prospect_id>
+            <visitor_page_view_count>1024</visitor_page_view_count>
+            <first_visitor_page_view_at>2015-09-03 11:57:01</first_visitor_page_view_at>
+            <last_visitor_page_view_at>2015-09-03 11:57:24</last_visitor_page_view_at>
+            <duration_in_seconds>1024</duration_in_seconds>
+            <campaign_parameter>Campaign Parameter</campaign_parameter>
+            <medium_parameter>Medium Parameter</medium_parameter>
+            <source_parameter>Source Parameter</source_parameter>
+            <content_parameter>Content Parameter</content_parameter>
+            <term_parameter>Term Parameter</term_parameter>
+            <created_at>2015-09-03 11:57:01</created_at>
+            <updated_at>2015-09-03 11:57:24</updated_at>
+        </visit>
+        <visit>
+            <id>37641</id>
+            <visitor_id/>
+            <prospect_id/>
+            <visitor_page_view_count/>
+            <first_visitor_page_view_at/>
+            <last_visitor_page_view_at/>
+            <duration_in_seconds/>
+            <campaign_parameter/>
+            <medium_parameter/>
+            <source_parameter/>
+            <content_parameter/>
+            <term_parameter/>
+            <created_at>2015-10-03 11:57:01</created_at>
+            <updated_at>2015-10-03 11:57:24</updated_at>
+        </visit>
+    </result>
+</rsp>
\ No newline at end of file
diff --git a/src/test/resources/mockResponses/visitRead.xml b/src/test/resources/mockResponses/visitRead.xml
new file mode 100644
index 0000000..d33850e
--- /dev/null
+++ b/src/test/resources/mockResponses/visitRead.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rsp stat="ok" version="1.0">
+    <visit>
+        <id>37640</id>
+        <visitor_id>123</visitor_id>
+        <prospect_id>123</prospect_id>
+        <visitor_page_view_count>1024</visitor_page_view_count>
+        <first_visitor_page_view_at>2015-09-03 11:57:01</first_visitor_page_view_at>
+        <last_visitor_page_view_at>2015-09-03 11:57:24</last_visitor_page_view_at>
+        <duration_in_seconds>1024</duration_in_seconds>
+        <campaign_parameter>Campaign Parameter</campaign_parameter>
+        <medium_parameter>Medium Parameter</medium_parameter>
+        <source_parameter>Source Parameter</source_parameter>
+        <content_parameter>Content Parameter</content_parameter>
+        <term_parameter>Term Parameter</term_parameter>
+        <created_at>2015-09-03 11:57:01</created_at>
+        <updated_at>2015-09-03 11:57:24</updated_at>
+        <visitor_page_views>
+            <visitor_page_view>
+                <id>111</id>
+                <url>http://go.pardot.com/l/1/2016-06-03/2khmg8</url>
+                <title>title1</title>
+                <created_at>2015-09-03 11:57:01</created_at>
+            </visitor_page_view>
+            <visitor_page_view>
+                <id>222</id>
+                <url>http://go.pardot.com/l/1/2016-06-03/2khmg8</url>
+                <title>title2</title>
+                <created_at>2015-09-03 11:57:01</created_at>
+            </visitor_page_view>
+        </visitor_page_views>
+    </visit>
+</rsp>
\ No newline at end of file
