diff --git a/inlineplz/linters/__init__.py b/inlineplz/linters/__init__.py
index f4b0a73..420508e 100644
--- a/inlineplz/linters/__init__.py
+++ b/inlineplz/linters/__init__.py
@@ -13,7 +13,7 @@ from inlineplz import parsers
 LINTERS = {
     'prospector': {
         'install': ['pip', 'install', 'prospector'],
-        'run': ['prospector', '--zero-exit'],
+        'run': ['prospector', '--zero-exit', '-o', 'json'],
         'dotfiles': ['.prospector.yaml'],
         'parser': parsers.ProspectorParser
     },
diff --git a/inlineplz/parsers/prospector.py b/inlineplz/parsers/prospector.py
index 68acb07..8146c2a 100644
--- a/inlineplz/parsers/prospector.py
+++ b/inlineplz/parsers/prospector.py
@@ -1,43 +1,31 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
+from collections import OrderedDict
+import json
+
 from inlineplz.parsers.base import ParserBase
 from inlineplz.message import Message
 
 
 class ProspectorParser(ParserBase):
-    """Parse default prospector output."""
+    """Parse json prospector output."""
 
     def parse(self, lint_data):
         messages = []
-        current_message = None
-        current_filename = ''
-        current_line = ''
-
-        messages_found = False
-
-        for line in lint_data.split('\n'):
-            # check for message block
-            if not line.strip():
-                continue
-            if not messages_found:
-                if line.strip() == 'Messages':
-                    messages_found = True
-                continue
-            # check for end of message block
-            elif line.strip() == 'Check Information':
-                break
-            # new filename
-            if not line.startswith(' '):
-                current_filename = line.strip()
-                continue
-            # new line number
-            elif not line.startswith('    '):
-                current_line = int(line.replace('  Line: ', '').strip())
-                current_message = Message(current_filename, current_line)
-                messages.append(current_message)
-                continue
-            # new content
-            current_message.comments.append(line.lstrip())
-
+        for msgdata in json.loads(
+            lint_data,
+            object_pairs_hook=OrderedDict
+        ).get('messages'):
+            msg = Message(
+                msgdata['location']['path'],
+                msgdata['location']['line']
+            )
+            msgbody = '{0}: {1} ({2})'.format(
+                msgdata['source'],
+                msgdata['message'],
+                msgdata['code']
+            )
+            msg.comments.append(msgbody)
+            messages.append(msg)
         return messages

refactor prospector parser to use json formatter
diff --git a/tests/parsers/test_prospector.py b/tests/parsers/test_prospector.py
index f673b81..fbba037 100644
--- a/tests/parsers/test_prospector.py
+++ b/tests/parsers/test_prospector.py
@@ -17,14 +17,12 @@ prospector_path = os.path.join(
 def test_prospector():
     with open(prospector_path) as inputfile:
         messages = prospector.ProspectorParser().parse(inputfile.read())
-        assert messages[0].content == '`pylint: syntax-error / invalid syntax`'
-        assert messages[0].line_number == 34
-        assert messages[0].path == 'docs/conf.py'
-        assert messages[1].content == '`pylint: unused-import / Unused Message imported from message`'
-        assert messages[1].line_number == 4
-        assert messages[1].path == 'inline-plz/parsers/base.py'
-        assert messages[9].content == ('```\npylint: misplaced-comparison-constant / Comparison '
-                                       'should be __name__ == \'__main__\' (col 3)\npylint: '
-                                       'pretend this is a real message\n```')
-        assert messages[9].line_number == 113
-        assert len(messages) == 11
+        assert messages[0].content == '`pep257: Missing docstring in public package (D104)`'
+        assert messages[0].line_number == 1
+        assert messages[0].path == 'inlineplz/util/__init__.py'
+        assert messages[1].content == '`pep257: Missing docstring in public package (D104)`'
+        assert messages[1].line_number == 1
+        assert messages[1].path == 'inlineplz/parsers/__init__.py'
+        assert messages[9].content == ('`pep257: One-line docstring should fit on one line with quotes (found 2) (D200)`')
+        assert messages[9].line_number == 1
+        assert len(messages) == 32
diff --git a/tests/testdata/parsers/prospector.txt b/tests/testdata/parsers/prospector.txt
index 7c9ed99..c6ec9f7 100644
--- a/tests/testdata/parsers/prospector.txt
+++ b/tests/testdata/parsers/prospector.txt
@@ -1,48 +1,407 @@
-Messages
-========
-
-docs\conf.py
-  Line: 34
-    pylint: syntax-error / invalid syntax
-
-inline-plz\parsers\base.py
-  Line: 4
-    pylint: unused-import / Unused Message imported from message
-  Line: 9
-    pylint: redefined-builtin / Redefining built-in 'input' (col 20)
-
-inline-plz\parsers\prospector.py
-  Line: 5
-    pylint: unused-import / Unused Message imported from message
-  Line: 8
-    pylint: redefined-builtin / Redefining built-in 'input' (col 20)
-  Line: 17
-    pylint: undefined-variable / Undefined variable 'message' (col 32)
-  Line: 24
-    pylint: undefined-variable / Undefined variable 'message' (col 32)
-  Line: 25
-    pylint: redefined-variable-type / Redefinition of current_line type from str to int (col 16)
-
-travis_pypi_setup.py
-  Line: 20
-    pylint: bare-except / No exception type(s) specified
-  Line: 113
-    pylint: misplaced-comparison-constant / Comparison should be __name__ == '__main__' (col 3)
-    pylint: pretend this is a real message
-  Line: 114
-    pylint: wrong-import-position / Import "import argparse" should be placed at the top of the module (col 4)
-
-
-
-Check Information
-=================
-         Started: 2016-01-09 12:50:17.649090
-        Finished: 2016-01-09 12:50:19.027461
-      Time Taken: 1.38 seconds
-       Formatter: grouped
-        Profiles: default, no_doc_warnings, no_test_warnings, strictness_medium, strictness_high, strictness_veryhigh, no_member_warnings
-      Strictness: None
-  Libraries Used:
-       Tools Run: dodgy, mccabe, pep8, profile-validator, pyflakes, pylint
-  Messages Found: 11
-
+{
+  "messages": [
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 1,
+        "path": "inlineplz\\util\\__init__.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D104",
+      "message": "Missing docstring in public package"
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 1,
+        "path": "inlineplz\\parsers\\__init__.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D104",
+      "message": "Missing docstring in public package"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 0,
+        "line": 9,
+        "path": "inlineplz\\main.py",
+        "module": "inlineplz.main",
+        "function": null
+      },
+      "code": "unused-import",
+      "message": "Unused parsers imported from inlineplz"
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 11,
+        "path": "inlineplz\\message.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D105",
+      "message": "Missing docstring in magic method"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 8,
+        "path": "setup.py",
+        "module": "setup",
+        "function": null
+      },
+      "code": "import-error",
+      "message": "Unable to import 'distutils.core'"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 0,
+        "line": 17,
+        "path": "setup.py",
+        "module": "setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"requirements\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 0,
+        "line": 23,
+        "path": "setup.py",
+        "module": "setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"test_requirements\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 12,
+        "path": "setup.py",
+        "module": "setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"readme\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 15,
+        "path": "setup.py",
+        "module": "setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"history\""
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 1,
+        "path": "travis_pypi_setup.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D200",
+      "message": "One-line docstring should fit on one line with quotes (found 2)"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 115,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"parser\""
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 69,
+        "path": "travis_pypi_setup.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D200",
+      "message": "One-line docstring should fit on one line with quotes (found 2)"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 27,
+        "line": 72,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": "prepend_line"
+      },
+      "code": "invalid-name",
+      "message": "Invalid variable name \"f\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 9,
+        "line": 106,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": "main"
+      },
+      "code": "redefined-outer-name",
+      "message": "Redefining name 'args' from outer scope (line 121)"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 32,
+        "line": 77,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": "prepend_line"
+      },
+      "code": "invalid-name",
+      "message": "Invalid variable name \"f\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 3,
+        "line": 113,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "misplaced-comparison-constant",
+      "message": "Comparison should be __name__ == '__main__'"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 27,
+        "line": 82,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": "load_yaml_config"
+      },
+      "code": "invalid-name",
+      "message": "Invalid variable name \"f\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 19,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "wrong-import-order",
+      "message": "standard import \"from urllib import urlopen\" comes before \"import yaml\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 0,
+        "line": 20,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "bare-except",
+      "message": "No exception type(s) specified"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 21,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "wrong-import-order",
+      "message": "standard import \"from urllib.request import urlopen\" comes before \"import yaml\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 32,
+        "line": 87,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": "save_yaml_config"
+      },
+      "code": "invalid-name",
+      "message": "Invalid variable name \"f\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 121,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "invalid-name",
+      "message": "Invalid constant name \"args\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 114,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "wrong-import-order",
+      "message": "standard import \"import argparse\" comes before \"import yaml\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 114,
+        "path": "travis_pypi_setup.py",
+        "module": "travis_pypi_setup",
+        "function": null
+      },
+      "code": "wrong-import-position",
+      "message": "Import \"import argparse\" should be placed at the top of the module"
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 1,
+        "path": "inlineplz\\interfaces\\__init__.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D104",
+      "message": "Missing docstring in public package"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 16,
+        "line": 36,
+        "path": "inlineplz\\parsers\\prospector.py",
+        "module": "inlineplz.parsers.prospector",
+        "function": "ProspectorParser.parse"
+      },
+      "code": "redefined-variable-type",
+      "message": "Redefinition of current_line type from str to int"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 12,
+        "line": 16,
+        "path": "inlineplz\\interfaces\\github.py",
+        "module": "inlineplz.interfaces.github",
+        "function": "GitHubInterface.__init__"
+      },
+      "code": "invalid-name",
+      "message": "Invalid attribute name \"gh\""
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 12,
+        "line": 18,
+        "path": "inlineplz\\interfaces\\github.py",
+        "module": "inlineplz.interfaces.github",
+        "function": "GitHubInterface.__init__"
+      },
+      "code": "redefined-variable-type",
+      "message": "Redefinition of self.gh type from github3.github.GitHub to github3.github.GitHubEnterprise"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 0,
+        "line": 4,
+        "path": "inlineplz\\interfaces\\github.py",
+        "module": "inlineplz.interfaces.github",
+        "function": null
+      },
+      "code": "unused-import",
+      "message": "Unused import os.path"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 20,
+        "line": 58,
+        "path": "inlineplz\\interfaces\\github.py",
+        "module": "inlineplz.interfaces.github",
+        "function": "GitHubInterface.position"
+      },
+      "code": "unused-variable",
+      "message": "Unused variable 'hunk_no'"
+    },
+    {
+      "source": "pylint",
+      "location": {
+        "character": 4,
+        "line": 14,
+        "path": "inlineplz\\interfaces\\github.py",
+        "module": "inlineplz.interfaces.github",
+        "function": "GitHubInterface.__init__"
+      },
+      "code": "too-many-arguments",
+      "message": "Too many arguments (6/5)"
+    },
+    {
+      "source": "pep257",
+      "location": {
+        "character": 0,
+        "line": 1,
+        "path": "inlineplz\\__init__.py",
+        "module": null,
+        "function": null
+      },
+      "code": "D104",
+      "message": "Missing docstring in public package"
+    }
+  ],
+  "summary": {
+    "strictness": "from profile",
+    "tools": [
+      "dodgy",
+      "mccabe",
+      "pep257",
+      "pep8",
+      "profile-validator",
+      "pyflakes",
+      "pylint"
+    ],
+    "formatter": "json",
+    "started": "2016-01-31 14:43:39.317922",
+    "profiles": ".prospector.yaml, full_pep8, doc_warnings, no_test_warnings, strictness_veryhigh, no_member_warnings",
+    "time_taken": "3.94",
+    "completed": "2016-01-31 14:43:43.256803",
+    "libraries": [],
+    "message_count": 32
+  }
+}

pip install -e .[dev]
parse_log_pytest
requirements.txt
numpy>=1.16.0 pandas>=1.0.0 pytest
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
cryptography==44.0.2
exceptiongroup==1.2.2
github3.py==4.0.1
idna==3.10
iniconfig==2.1.0
-e git+https://github.com/guykisel/inline-plz.git@59cb7f9721ca3390fa31c48583e786e3728e8f1a#egg=inlineplz
numpy==2.0.2
packaging==24.2
pandas==2.2.3
pluggy==1.5.0
pycparser==2.22
PyJWT==2.10.1
pytest==8.3.5
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.32.3
six==1.17.0
tomli==2.2.1
tzdata==2025.2
unidiff==0.7.5
uritemplate==4.1.1
urllib3==2.3.0
xmltodict==0.14.2

name: inline-plz
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - cryptography==44.0.2
      - exceptiongroup==1.2.2
      - github3-py==4.0.1
      - idna==3.10
      - iniconfig==2.1.0
      - numpy==2.0.2
      - packaging==24.2
      - pandas==2.2.3
      - pluggy==1.5.0
      - pycparser==2.22
      - pyjwt==2.10.1
      - pytest==8.3.5
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.32.3
      - six==1.17.0
      - tomli==2.2.1
      - tzdata==2025.2
      - unidiff==0.7.5
      - uritemplate==4.1.1
      - urllib3==2.3.0
      - xmltodict==0.14.2
prefix: /opt/conda/envs/inline-plz

tests/parsers/test_prospector.py::test_prospector
inlineplz/parsers/prospector.py inlineplz/linters/__init__.py
inlineplz/parsers/prospector.py inlineplz/linters/__init__.py